Application 全局应用

783 阅读3分钟

Application 是维护应用全局状态的基类,Android 系统会在启动应用进程时创建一个对应的 Application 对象。所以当我们需要创建全局变量的时候,不需要再像 Java 那样需要创建 public 权限的 static 变量,而直接在 Application 中去实现。其他组件只需要调用 Context 的 getApplicationContext 或者 getApplication(在 Activity 中) 来获得一个 Application 对象,再做出相应的处理。

自定义 Application

我们可以通过创建一个子类,并在 AndroidManifest.xml 的<application>标签中将该子类的标准名称指定为”android:name” 属性来设定为自己的实现类。

public class MyApplication extends Application {
    // ...
}

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="cn.tim.custom_application">
    <application
        android:
        ...
        android:theme="@style/AppTheme">
        ...
    </application>
</manifest>

MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Log.i(TAG, "onCreate: " + getApplication());
}

打印出来的确实自定义的 Application 类对象:

MainActivity: onCreate: cn.tim.custom_application.MyApplication@9e7a3660

Application对象生命周期

Application 对象诞生于其它任何组件对象之前,并且一直存活,直到应用进程结束。Application 对象由 Android 系统管理,它的回调函数都运行于 UI 线程。

public class MyApplication extends Application {
    private static final String TAG = "MyApplication";

    // Application对象被创建的时候会调用
    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "onCreate: " + this);
        Log.i(TAG, "onCreate: " + Thread.currentThread());
    }

    // 系统配置变更,如横屏变成竖屏、系统语言更改
    @Override
    public void onConfigurationChanged(@NonNull Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        Log.i(TAG, "onConfigurationChanged: " + newConfig );
    }

    // 系统内存吃紧的时候被调用
    @Override
    public void onLowMemory() {
        super.onLowMemory();
        Log.i(TAG, "onLowMemory: ");
    }
}

Application 对象的作用

Application 对象全局可访问,且全程陪同应用进程。所以特别适合完成以下任务:初始化全应用所需的服务、共享全局状态、监听配置信息改变、监听 Activity 生命周期

初始化全应用所需的服务:在 Application 对象被创建时会调用 onCreate() 方法,此时用来初始化全应用所需的服务是个不错的选择,但是最好执行耗时操作,否则会拖慢应用程序启动速度。

共享全局状态:另外使用 Application 对象实现数据共享、数据缓存也是一个不错的选择。Application 对象可以获取应用程序当前的内存使用情况,及时释放资源,从而避免被系统杀死。

监听配置信息改变:如屏幕旋转,系统语言切换等(下面是手机开启横屏的示例)。

监听 Activity 生命周期:监听应用程序内所有 Activity 的生命周期。

Application对象 VS 静态单例

Application 对象与静态单例都可以实现应用全局状态的共享,以共享 Otto 的 Bus 对象为例:

implementation group: 'com.squareup', name: 'otto', version: '1.3.8'

这是使用 Application 对象进行全局共享的示例:

MyApplication.java

public class MyApplication extends Application {
    private Bus bus;

    public Bus getBus() {
        return bus;
    }
    
    @Override
    public void onCreate() {
        super.onCreate();
        bus = new Bus();
    }
    
    ...
}

MainActivity.java

@Override
protected void onResume() {
    super.onResume();
    MyApplication application = (MyApplication) getApplication();
    Bus bus = application.getBus();
    bus.register(this);
}

@Override
protected void onPause() {
    super.onPause();
    MyApplication application = (MyApplication) getApplication();
    Bus bus = application.getBus();
    bus.unregister(this);
}

这是使用静态单例进行全局共享的示例:
BusProvider.java

public class BusProvider {
    private BusProvider(){}
    private static final Bus bus = new Bus();

    public static Bus getBus(){
        return bus;
    }
}

OtherActivity.java

@Override
protected void onResume() {
    super.onResume();
    BusProvider.getBus().register(this);
    Log.i(TAG, "onResume: bus = " + BusProvider.getBus());
}

@Override
protected void onPause() {
    super.onPause();
    BusProvider.getBus().unregister(this);
    Log.i(TAG, "onPause: bus = " + BusProvider.getBus());
}

1、静态单例模块化程度更好
2、Application 就是一个 context,所以有访问资源的能力
3、静态单例可以接受 context 参数
4、Application 对象能接收系统回调,自动知悉系统环境变化
5、Application 对象的生命周期由系统控制