Android开发-Application

一、Application 是什么?

Application 是 Android 四大组件之一(虽无需在 Manifest 中注册),代表整个应用进程

  • 创建时机 :在任何 ActivityService 启动前,由系统创建。
  • 生命周期:与应用进程生命周期一致,进程不退出,它就一直存在。
  • 全局唯一 :一个应用进程中只有一个 Application 实例。

📌 官方定义Application 类在应用启动时被实例化,可用于执行全局初始化维护全局应用状态

二、基本使用:自定义 Application

1. 创建自定义 Application

java 复制代码
public class MyApplication extends Application {
    
    private static MyApplication instance;
    private String globalConfig;
    private boolean isUserLoggedIn;

    @Override
    public void onCreate() {
        super.onCreate();
        // 应用创建时调用,仅一次
        instance = this;
        
        // 初始化操作
        initCrashHandler();
        initAnalytics();
        initNetwork();
        loadGlobalSettings();
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        // 系统内存不足时调用,可在此释放非关键资源
        Log.w("MyApp", "Low Memory Warning!");
    }

    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
        // 更精细的内存释放回调
        if (level >= TRIM_MEMORY_MODERATE) {
            // 释放缓存等资源
        }
    }

    // 提供全局上下文(谨慎使用)
    public static MyApplication getInstance() {
        return instance;
    }

    // 全局 Getter/Setter
    public String getGlobalConfig() {
        return globalConfig;
    }

    public void setGlobalConfig(String config) {
        this.globalConfig = config;
    }

    public boolean isUserLoggedIn() {
        return isUserLoggedIn;
    }

    public void setUserLoggedIn(boolean loggedIn) {
        this.isUserLoggedIn = loggedIn;
    }
}

2. 在 AndroidManifest.xml 中注册

XML 复制代码
<application
    android:name=".MyApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">
    
    <!-- Activities, Services, etc. -->
    
</application>

必须注册 ,否则 onCreate() 不会被调用。

三、核心应用场景

1. 全局初始化(最常见用途)

onCreate() 中初始化第三方库,确保在任何组件使用前完成。

java 复制代码
private void initAnalytics() {
    // 如:友盟、Firebase、Bugly
    AnalyticsKit.init(this);
    AnalyticsKit.setChannel("google_play");
}

private void initNetwork() {
    // 如:OkHttp, Retrofit
    OkHttpClient client = new OkHttpClient.Builder()
        .addInterceptor(new LoggingInterceptor())
        .build();
    ApiService.init(client);
}

private void initCrashHandler() {
    // 全局异常捕获
    Thread.setDefaultUncaughtExceptionHandler((thread, ex) -> {
        Log.e("Crash", "App crashed!", ex);
        saveCrashLog(ex);
        // 上报崩溃信息
        CrashReport.postCatchedException(ex);
        // 退出进程
        android.os.Process.killProcess(android.os.Process.myPid());
    });
}

2. 维护全局状态

存储应用级别的状态,避免频繁传递参数。

java 复制代码
// 在登录 Activity 中
MyApplication app = (MyApplication) getApplication();
app.setUserLoggedIn(true);

// 在其他 Activity 中检查
if (((MyApplication) getApplication()).isUserLoggedIn()) {
    showUserProfile();
}

⚠️ 注意 :简单状态可用,复杂状态建议用 ViewModelRepository

3. 提供全局上下文

java 复制代码
// 在工具类中获取 Context
public class NetworkUtil {
    public static boolean isNetworkAvailable() {
        Context context = MyApplication.getInstance();
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        return activeNetwork != null && activeNetwork.isConnected();
    }
}

⚠️ 风险:可能导致内存泄漏(见下文)。

4. 监听组件生命周期(Application.ActivityLifecycleCallbacks)

监控所有 Activity 的生命周期,用于埋点、会话统计等。

java 复制代码
@Override
public void onCreate() {
    super.onCreate();
    
    registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
        private int resumed = 0;
        private int paused = 0;

        @Override
        public void onActivityResumed(@NonNull Activity activity) {
            resumed++;
            if (resumed == 1 && paused > 0) {
                // 应用从后台回到前台
                Log.d("Lifecycle", "App Brought to Foreground");
                onAppForeground();
            }
        }

        @Override
        public void onActivityPaused(@NonNull Activity activity) {
            paused++;
            if (resumed == paused) {
                // 应用进入后台
                Log.d("Lifecycle", "App Sent to Background");
                onAppBackground();
            }
        }

        // 实现其他回调...
        @Override public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {}
        @Override public void onActivityStarted(@NonNull Activity activity) {}
        @Override public void onActivityStopped(@NonNull Activity activity) {}
        @Override public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {}
        @Override public void onActivityDestroyed(@NonNull Activity activity) {}
    });
}

private void onAppForeground() {
    // 如:刷新数据、重新连接 WebSocket
}

private void onAppBackground() {
    // 如:断开非必要连接、保存状态
}

5. 多进程支持

如果应用有多个进程(如 :remote),每个进程都会创建一个独立的 Application 实例。

XML 复制代码
<service android:name=".RemoteService" android:process=":remote" />
java 复制代码
@Override
public void onCreate() {
    super.onCreate();
    String processName = getProcessName();
    Log.d("MyApp", "Application created in process: " + processName);
    
    if (":remote".equals(processName)) {
        // 仅在远程进程初始化特定服务
        initRemoteService();
    } else {
        // 主进程初始化
        initMainProcessComponents();
    }
}

四、最佳实践与高级技巧

1. 避免滥用全局变量

  • ❌ 不要将大量数据、Bitmap、Context 存入全局变量。
  • ✅ 优先使用 SharedPreferencesRoom 或内存缓存(LruCache)。

2. 懒加载与按需初始化

避免在 onCreate() 中执行耗时操作,阻塞 UI 启动。

java 复制代码
private volatile boolean analyticsInited = false;

public void ensureAnalyticsInited() {
    if (!analyticsInited) {
        synchronized (this) {
            if (!analyticsInited) {
                new Thread(() -> {
                    // 耗时初始化
                    AnalyticsKit.init(this);
                    analyticsInited = true;
                }).start();
            }
        }
    }
}

3. 使用 ContentProvider 进行初始化(替代方案)

对于库的初始化,可使用 ContentProvider 避免依赖 Application

java 复制代码
public class InitProvider extends ContentProvider {
    @Override
    public boolean onCreate() {
        // 在应用启动时自动调用
        MyLibrary.init(getContext());
        return true;
    }
    // ... 其他方法返回 null
}
XML 复制代码
<provider
    android:name=".InitProvider"
    android:authorities="${applicationId}.initprovider"
    android:multiprocess="false"
    android:exported="false" />

优点 :库无需用户继承 Application

4. 内存泄漏防护

  • ❌ 避免将 ActivityView 的引用存入 Application
  • ✅ 使用 WeakReference 包装长生命周期持有的对象。
java 复制代码
private WeakReference<SomeListener> listenerRef;

public void setGlobalListener(SomeListener listener) {
    this.listenerRef = new WeakReference<>(listener);
}

public SomeListener getGlobalListener() {
    return listenerRef != null ? listenerRef.get() : null;
}

5. 配置多 flavor 的 Application

不同构建变体(如 debug, release)可使用不同的 Application 类。

Groovy 复制代码
android {
    flavorDimensions "version"
    productFlavors {
        dev {
            applicationIdSuffix ".dev"
            // 使用不同的 Application 类
            manifestPlaceholders = [applicationClass: "com.example.DevApplication"]
        }
        prod {
            manifestPlaceholders = [applicationClass: "com.example.ProdApplication"]
        }
    }
}
XML 复制代码
<application
    android:name="${applicationClass}"
    ... >
</application>

五、常见陷阱与解决方案

陷阱 后果 解决方案
在 Application 中持有 Activity Context 内存泄漏,Activity 无法回收 使用 getApplicationContext()
onCreate() 执行耗时操作 应用启动慢,ANR 风险 异步初始化或懒加载
过度使用全局变量 内存占用高,状态混乱 用持久化存储或合理架构替代
未处理多进程 资源重复初始化,数据不一致 检查进程名,按需初始化
忘记注册 Application 自定义逻辑不生效 检查 AndroidManifest.xml

六、Application vs 其他组件

对比项 Application Activity Service
生命周期 全局,最长 短暂,用户交互 中等,后台运行
唯一性 进程内唯一 可多个实例 可多个实例
用途 全局初始化、状态 UI 界面 后台任务
Context 类型 getApplicationContext() Activity Context Service Context

七、动手实践

  1. 创建 MyApplication,初始化一个日志库(如 Timber)。
  2. 实现 ActivityLifecycleCallbacks,打印应用前后台切换日志。
  3. 添加一个全局配置项(如 API Base URL),并通过 BuildConfig 动态设置。
  4. 实现一个简单的全局异常捕获器。

八、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
hnlgzb2 小时前
常见的Android Jetpack库会有哪些?这些库中又有哪些常用类的?
android·android jetpack
钛态5 小时前
Flutter 三方库 http_mock_adapter — 赋能鸿蒙应用开发的高效率网络接口 Mock 与自动化测试注入引擎(适配鸿蒙 HarmonyOS Next ohos)
android·网络协议·flutter·http·华为·中间件·harmonyos
王码码20355 小时前
Flutter for OpenHarmony:Flutter 三方库 algoliasearch 毫秒级云端搜索体验(云原生搜索引擎)
android·前端·git·flutter·搜索引擎·云原生·harmonyos
左手厨刀右手茼蒿5 小时前
Flutter for OpenHarmony: Flutter 三方库 shamsi_date 助力鸿蒙应用精准适配波斯历法(中东出海必备)
android·flutter·ui·华为·自动化·harmonyos
代码飞天6 小时前
wireshark的高级使用
android·java·wireshark
2501_915918417 小时前
苹果App Store上架审核卡住原因分析与解决方案指南
android·ios·小程序·https·uni-app·iphone·webview
skiy7 小时前
MySQL Workbench菜单汉化为中文
android·数据库·mysql
小小小点7 小时前
Android四大常用布局详解与实战
android
MinQ8 小时前
binder和socket区别及原理
android
Ehtan_Zheng9 小时前
Jetpack Compose 中绘制发光边框的多种方式
android