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. 实现一个简单的全局异常捕获器。

八、结语

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

相关推荐
2501_9159090629 分钟前
原生 iOS 开发全流程实战,Swift 技术栈、工程结构、自动化上传与上架发布指南
android·ios·小程序·uni-app·自动化·iphone·swift
2501_9159090636 分钟前
苹果软件混淆与 iOS 代码加固趋势,IPA 加密、应用防反编译与无源码保护的工程化演进
android·ios·小程序·https·uni-app·iphone·webview
2501_9160074737 分钟前
苹果软件混淆与 iOS 应用加固实录,从被逆向到 IPA 文件防反编译与无源码混淆解决方案
android·ios·小程序·https·uni-app·iphone·webview
介一安全1 小时前
【Frida Android】基础篇6:Java层Hook基础——创建类实例、方法重载、搜索运行时实例
android·java·网络安全·逆向·安全性测试·frida
沐怡旸4 小时前
【底层机制】【Android】深入理解UI体系与绘制机制
android·面试
啊森要自信4 小时前
【GUI自动化测试】YAML 配置文件应用:从语法解析到 Python 读写
android·python·缓存·pytest·pip·dash
下位子6 小时前
『AI 编程』用 Codex 开发识字小帮手应用
android·openai·ai编程
Zender Han6 小时前
Flutter 实现人脸检测 — 使用 google_mlkit_face_detection
android·flutter·ios
君逸臣劳6 小时前
玩Android Flutter版本,通过项目了解Flutter项目快速搭建开发
android·flutter
叫我龙翔6 小时前
【MySQL】从零开始了解数据库开发 --- 基本查询
android·mysql·数据库开发