4.4 Application基础

本节介绍Android重要组件Application的基本概念和常见用法。首先说明Application的生命周期,接着利用Application的持久特性实现App内部全局内存中的数据保存和获取。

4.4.1 Application的生命周期

Application是Android的一大组件,在App运行过程中有且仅有一个Application对象贯穿整个生命周期。打开AndroidManifest.xml时会发现activity节点的上级正是application节点,只是默认的application节点没有指定name属性,不像activity节点默认指定name属性值为.MainActivity,让人知晓这个activity的入口代码是MainActivity.java。现在我们给application节点加上name属性,看看其庐山真面目。

(1)打开AndroidManifest.xml,给application节点加上name属性,表示application的入口代码是MainApplication.java。

                android:name=".MainApplication"

(2)创建MainApplication类,该类继承自Application,可以重写的方法主要有以下4个。

● onCreate:在App启动时调用。

● onTerminate:在App退出时调用(按字面意思)。

● onLowMemory:在低内存时调用。

● onConfigurationChanged:在配置改变时调用,例如从竖屏变为横屏。

(3)运行App,同时开启日志的打印。但是只在一开始看到MainApplication的onCreate操作(先于Activity的onCreate),却始终无法看到它的onTerminate操作,无论是自行退出还是强行杀死App的进程,日志都不会打印onTerminate。

信不信,无论你怎么折腾,这个onTerminate都不会出来。Android明明提供了这个函数,同时提供了关于该函数的解释,说明文字如下:This method is for use in emulated process environments. It will never be called on a production Android device, where processes are removed by simply killing them; no user code (including this callback) is executed when doing so。这段话的意思是该方法是供模拟环境用的,在真机上永远不会被调用,无论是直接杀进程还是代码退出。

现在很明确了,onTerminate方法就是个摆设,中看不中用。如果读者想在App退出前做资源回收操作,那么千万不要放在onTerminate方法中。

4.4.2 利用Application操作全局变量

C/C++有全局变量,因为全局变量保存在内存中,所以操作全局变量就是操作内存,内存的读写速度远比读写数据库或读写文件快得多。全局的意思是其他代码都可以引用该变量,因此全局变量是共享数据和消息传递的好帮手。不过,Java没有全局变量的概念。与之比较接近的是类里面的静态成员变量,该变量可被外部直接引用,并且在不同地方引用的值是一样的(前提是在引用期间不能修改该变量的值),所以可以借助静态成员变量实现类似全局变量的功能。

前面花费很大功夫介绍Application的生命周期,目的是说明其生命周期覆盖App运行的全过程。不像短暂的Activity生命周期,只要进入别的页面,原页面就被停止或销毁。因此,通过利用Application的持久存在性可以在Application对象中保存全局变量。

适合在Application中保存的全局变量主要有下面3类数据:

(1)会频繁读取的信息,如用户名、手机号等。

(2)从网络上获取的临时数据,为节约流量、减少用户等待时间,想暂时放在内存中供下次使用,如logo、商品图片等。

(3)容易因频繁分配内存而导致内存泄漏的对象,如Handler对象等。

要想通过Application实现全局内存的读写,得完成以下3项工作:

(1)写一个继承自Application的类MainApplication。该类要采用单例模式,内部声明自身类的一个静态成员对象,在创建App时把自身赋值给这个静态对象,然后提供该静态对象的获取方法getInstance。

(2)在Activity中调用MainApplication的getInstance方法,获得MainApplication的一个静态对象,通过该对象访问MainApplication的公共变量和公共方法。

(3)不要忘了在AndroidManifest.xml中注册新定义的Application类名,即在application节点中增加android:name属性,值为.MainApplication。

下面继续演示全局内存的读写效果,如图4-15所示。App把注册信息保存到MainApplication的全局变量中,然后在另一个页面从MainApplication的全局变量中读取保存好的注册信息,如图4-16所示。

图4-15 注册信息保存到全局内存

图4-16 从全局内存读取注册信息

下面是自定义MainApplicaton类的代码:

        public class MainApplication extends Application {
            private static MainApplication mApp;
            public HashMap<String, String> mInfoMap = new HashMap<String, String>();


            public static MainApplication getInstance() {
                return mApp;
            }


            @Override
            public void onCreate() {
                super.onCreate();
                mApp = this;
            }
        }

完成以上编码后,Activity页面代码即可直接通过MainApplication.getInstance().mInfoMap对全局变量进行增、删、改、查操作。