Android应用程序运行时会先读取AndroidManifest.xml清单文件,根据清单文件中的配置信息设置应用程序的基本信息,通过过滤条件查找到入口的Activity,并查找到对应的类名,然后创建该类的实例。接着会调用该类的onCreate
方法设置Activity显示界面。
Android应用的启动流程
你所看到的手机桌面Launcher也是继承自Activity的,当安装完以一个APP之后会在手机桌面Launcherr上生成 以一个对应的APP图标。首次点击图标时Launcher会启动图标对应APP的首页Activity,一般而言启动的都是项目工程中的MainActivity,其实这个过程是一个Activity的启动的过程,与在APP内部启动一个Activity不同的是:点击桌面Launcher首次启动APP时会先去建立APP对应的进程,然后再执行ActivityThread的main()方法去创建对应的Application,最后再启动首页Activity。
当用户点击APP图标时会启动Launcher与应用程序,Launcher继承自Activity并实现了点击长按监听。此时Luncher会通过Intent发送startActivity请求,通过binder机制调用ActivityManagerService通讯,经过一些列操作后调用startProcessLocked方法,并通过Socket通道传递参数给Zygote进程。此时Zygote进程会调用ZygoteInit.main()方法产生一个新的进程并返回PID,最后调用ActivityThread.main方法来实例化ActivityThread对象。此时Activity进程真正开始...
当点击桌面Launcher首次进入APP时,会走Activity的startActivity()的过程,在启动一个新的Activity之前会先执行当前Activity的onPause()方法,会将当前Activity给Pause掉。如果是点击桌面Launcher首次进入APP的话,这个当前的Activity指的是桌面Launcher的Activity。当前Activity执行onPause()之后,如果当前应用的进程已经创建,这种情况下指得是在APP内部的Activity的跳转,那么就会去通过ActivityManagerService中持有的ActivityThread中的ApplicationThread这个Binder对象来立即创建一个新的Activity,并执行该Activity声明周期的方法。如果当前应用的进程没有创建也就是首次进入APP,那么这个时候会先通过Process.start()方法来创建一个进程,在创建的过程中会去调用ActivityThread的main()方法,在这个main()方法中会创建一些必备的东西比如主线程的Looper等,并且在main()方法中会执行Application的创建过程,通过ActivityManagerService来创建一个Application,在创建完成后会启动一个Activity,这个Activity值得是默认启动的首页Activity,也就是通常所说的MainActivity。
清单文件AndroidManifest.xml
Application的创建过程
整个Android应用启动的入口是ActivityThread的main()方法,Application的创建也是在这个main()方法中。
Application类
onCreate
方法。onCreate
创建、onConfigurationChanged
系统配置变更(包括屏幕方向变化、系统语言变化等)、onLowMemory
释放内存Application和Activity、Service一样都是Android框架的系统组件,当APP启动时系统会创建一个Application对象用来存储系统的信息。Android系统会自动为每个程序运行时创建一个Application类的对象且只创建一个,所以Application可以说是单例(singleton)模式的一个类。
通常无需手动指定Application,系统会自动创建。如果需要手工创建只需要创建一个继承自Application的类并在AndroidManifest.xml清单文件中的
标签中进行注册,也就是给
标签增加android:name
属性。
继承Application的类主要需要重写父类的onCreate()
方法,因为android.app.Application
包中的onCreate()
方法才是真正的Android程序的入口点。在onCreate()
方法主要用于创建时初始化变量的值,然后在整个应用中的各个文件中就可以对该变量进行操作。
$ vim MainApplication.java
package com.weihuagu.receiptnotice;
import android.app.Application;
import android.content.Intent;
import com.tao.admin.loglib.TLogApplication;
import com.tao.admin.loglib.IConfig;
public class MainApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
startNotificationService();
initLogConfig();
}
private void initLogConfig(){
TLogApplication.initialize(this);
IConfig.getInstance().isShowLog(false)//是否在logcat中打印log,默认不打印
.isWriteLog(true)//是否在文件中记录,默认不记录
.tag("GoFileService");//logcat 日志过滤tag
}
private void startNotificationService(){
startService(new Intent(this, NotificationCollectorMonitorService.class));
}
}
android.app.Application
类包含了四个公开的方法
void onConfigurationChanged(Configuration newConfig)
void onCreate()
void onLowMemory()
void onTerminate()
Application的生命周期
onCreate
在创建应用程序时创建onTerminate
当终止应用程序对象时调用,不保证一定被调。Application
对象的onTerminate()
方法而直接终止进程。onLowMemory
当后台程序已经终止资源还匮乏时会调用此方法,好的应用程序一般会在此方法中释放一些不必要的资源来应付当后台程序已经终止,前台应用程序内存仍不足够时的情况。onConfigurationChanged
配置改变时触发Application被杀死的情况
为了决定在内存较低时杀掉哪个进程,Android会根据运行在这些进程内的组件以及状态将进程划分成一个重要程度层次,其重要程度按一下规则排序。
onResume()
方法被调用时),也可以是持有一个正在运行的IntentReceiver(正在执行自己的onReceiveIntent()
方法)的进程。在系统中,只会有少数这样的进程,除非内存已经低到不够这些进程运行,否则系统不会主动杀掉这些进程。此时设备通常已经达到需要内存整理的状态,所以杀掉这些进程是为了不让用户界面停止响应。当启动Application时系统会创建一个进程ID(PID),所有的Activity都会在此进程上运行。在Application创建的时候会初始化全局变量,同一个应用的所有Activity都可以获取到这些全局变量的值。换句话说,在某个Activity中改变了全局变量的值会影响到同一个应用中其他Activity中的值。
Application对象的生命周期是整个程序中最长的,基本上等同于应用的生命周期。因为是全局单例的,所以在 不同的Activity、Service中获取得到的对象都是同一个对象。因此可以通过Application来进行一些操作,比如数据传递、数据共享、数据缓存等。
Application传递数据
假如有一个ActivityA跳转到ActivityB并需要推荐一些数据,通常的做法是使用Intent.putExtra()
方法让Intent
携带,或者使用一个Bundle将信息让Intent推荐Bundle对象实现传递。但这样做的问题在于Intent和Bundle所能携带的数据类型都是基本数据类型,如果想要实现复杂数据类型传递就比较麻烦,通常需要实现Serializable或Parcellable接口,这其实是Android的一种IPC数据传输的方法。如果两个Activitty在同一个进程中为什么还需要这么麻烦呢?只需将要传递的数据引用传递过去即可。实现的基本思路是在Application中创建一个HashMap,以字符串为索引,Object为值得方式。在ActivityA中将需要传递的对象放入HashMap,然后通过Intent或其他途径将索引字符串传递给ActivityB,AactivityB会根据这个字符串在HashMap中获取出目标对象。只要再向下转型就实现了对象的传递。
Application数据缓存
一般习惯会再Application中建立两个HashMap,一个用于数据传递,一个用于缓存数据。比如有一个Activity需要从网站中获取数据,获取完毕后可以将数据缓存到Application中,当页面设置到其他Activity再回来时,可以直接使用给缓存好的数据。但如果需要缓存一些大量数据,最好是缓存一些软引用(SoftReference),并将这些数据缓存到本地ROM或SD卡上。如果再Application中的缓存不存在,可以从本地缓存中查找,如果本地缓存的数据也不存在则再从网络中获取。