Android Application的生命周期

导读

  • 移动开发知识体系总章(Java基础、Android、Flutter)
  • Application是什么
  • Application生命周期
  • 使用Application传递数据
  • 使用Application数据缓存
  • Application的context
  • Application的oncreate方法会执行几次,会不会多次执行?
  • 使用Application避免一些内存泄漏

Application是什么

Application和Activity、Service一样是Android框架的一个系统组件,当Android程序启动时系统会创建一个 Application对象,用来存储系统的一些信息。
Application的生命周期等于这个程序的生命周期,又因为Application是全局的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象。所以通过Application来进行一些数据传递、数据共享、数据缓存等操作。

一般写Demo是不需要指定一个Application的,这时系统会自动帮我们创建;而实际项目中基本上都是需要创建自己的Application的,创建一个类继承 Application并在AndroidManifest清单文件中的Application标签中进行注册(只需要给Application标签增加个name属性把自己的 Application的名字定入即可)。android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,所以Application可以说是单例 (singleton)模式的一个类。

Application生命周期

  1. onConfigurationChanged( ) :在配置被改变时触发 。
  2. onCreate() :在程序创建时创建。
  3. onLowMemory() :内存不够时触发。
  4. onTerminate() :当终止程序时调用 但是不能保证一定调用
  5. onTrimMemory() :在内存清理时触发
public class App extends Application {
    @Override
    public void onCreate() {
        // 程序创建的时候执行
        Log.d(TAG, "onCreate");
        super.onCreate();
    }
    @Override
    public void onTerminate() {
        // 程序终止的时候执行
        Log.d(TAG, "onTerminate");
        super.onTerminate();
    }
    @Override
    public void onLowMemory() {
        // 低内存的时候执行
        Log.d(TAG, "onLowMemory");
        super.onLowMemory();
    }
    @Override
    public void onTrimMemory(int level) {
        // 程序在内存清理的时候执行
        Log.d(TAG, "onTrimMemory");
        super.onTrimMemory(level);
    }
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        Log.d(TAG, "onConfigurationChanged");
        super.onConfigurationChanged(newConfig);
    }
}

使用Application传递数据

在android中通常会使用Intent(Bundle)进行数据通信,但一般为简单数据类型,如数据类型相对复杂(如对象)则需要实现 Serializable或者Parcelable接口,其实可以使用Application传递复杂数据。

基本思路是这样的。在Application中创建一个HashMap ,以字符串为key,Object为value这样我们的HashMap就可以存储任何类型的对象了

使用Application数据缓存

既然可以在Application中使用HashMap 进行传递数据,自然是可以进行一些缓存动作了,不过笔者基本没有这样操作过,同时需要注意内存泄漏。

Application的Context

  • Context是一个应用程序环境的信息,即上下文。
  • 该类是一个抽象(abstract class)类,Android提供了该抽象类的具体实现类(后面我们会讲到是ContextIml类)。
  • 通过它我们可以获取应用程序的资源和类,也包括一些应用级别操作,例如:启动一个Activity,发送广播,接受Intent信息 等


    Android Application的生命周期_第1张图片
    Context

可以看到Activity、Service、Application都是Context的子类。
也就是说,Android系统的角度来理解:Context是一个场景,代表与操作系统的交互的一种过程。从程序的角度上来理解:Context是个抽象类,而Activity、Service、Application等都是该类的一个实现。

Application的oncreate方法会执行几次,会不会多次执行?

通常情况下,App默认开启一个进程,进程名就是AndroidManifest.xml文件中我们项目的包名,所有的基本组件都是在这个进程中进行,Application的onCreate方法会被执行一次。但是如果我们工程涉及到多进程,那么就会出现Application的onCreate方法被多次执行情况。

解决oncreate方法多次被调用:

1、定义获取进程的方法

    private String getProcessName(Context context) {
        try {
            ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
            List runningApps = am.getRunningAppProcesses();
            if (runningApps == null) {
                return null;
            }
            for (ActivityManager.RunningAppProcessInfo proInfo : runningApps) {
                if (proInfo.pid == android.os.Process.myPid()) {
                    if (proInfo.processName != null) {
                        return proInfo.processName;
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

2、在onCreate方法中进行比对

 @Override
    public void onCreate() {
        super.onCreate();
        String processName = getProcessName(this);
        if (processName!= null) {
            String pkName = this.getPackageName();
            //只有主进程,才执行后续逻辑
            if(processName.equals(pkName)==false) {
                return;
            }
        }

使用Application避免一些内存泄漏(Memory Leak)

在Java中内存泄漏是指某个(某些)对象已经不在被使用应该被GC回收,但有一个对象持有这个对象的引用而阻止这个对象被回收。

比如在项目中经常用到单例模式,而很多单例是需要传递Context的,由于sInstance是一个static且强引用的,若此时传递Context的是xxxActivity.this,那么这个xxxActivity就不会被内存回收,就会造成内存泄漏。

解决办法就是Context传递context.getApplicationContext()

ps 经常导致内存泄漏核心原因分析(跳转连接)

以下内容等待被编辑到指定位置
ps 经常导致内存泄漏核心原因分析(跳转连接)

keeping a long-lived reference to a Context

上述是常见的内存泄漏的提示,即持有一个context的对象,从而GC不能回收,为什么会有这样的情况呢

  • 一个View的作用域超出了所在的Activity的作用域,比如一个static的View或者把一个View cache到了application
  • 某些与View关联的Drawable的作用域超出了Activity的作用域.
  • Runnable对象:比如在一个Activity中启用了一个新线程去执行一个任务,在这期间这个Activity被系统回收了, 但Runnalbe的 任务还没有执行完毕并持有Activity的引用而泄漏,但这种泄漏一般来泄漏一段时间,只有Runnalbe的线程执行完闭,这个 Activity又可以被正常回收了。
  • 内存类的对象作用域超出Activity的范围:比如定义了一个内存类来存储数据,又把这个内存类的对象传给了其它Activity、Service等。因为内部类的对象会持有当前类的引用,所以也就持有了Context的引用。
    解决方法是如果不需要当前的引用把内部类写成static或者把内部类抽取出来变成一个单独的类,或者作用域超出Activity的作用域。
    Out Of Memery Error 在Android中每一个程序所分到的内存大小是有限的,如果超过了这个数就会报Out Of Memory Error。 Android给程序分配的内存大小与手机硬件有关,以下是一些手机的数据:
    G1:16M Droid:24 Nexus One:32M Xoom:48Ms
    所以尽量把程序中的一些大的数据cache到本地文件。以免内存使用量超标。
    记得数据传递完成之后,把存放在application的HashMap中的数据remove掉,以免发生内存的泄漏。

你可能感兴趣的:(Android Application的生命周期)