Application有什么作用?
- 保存应用进程内的全局变量。
- 初始化资源。
- 提供应用上下文。
注意点:
应用启动时会在Application的onCreate()方法中初始化一些全局资源,系统配置,三方sdk等。此处需要注意一点,App可能会有多个进程:主进程、三方sdk的一些进程,初始sdk的时候需要注意在相应的进程中去初始化,避免浪费资源。
Application的生命周期
- 构造函数
- attachBaseContext
- onCreate
Application初始化
ActivityThread.java
public static void main(String[] args) {
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);//1
Looper.loop();
}
private void attach(boolean system) {
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread);//2
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);//3
Binder.restoreCallingIdentity(origId);
}
}
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
...
/通过binder,跨进程调用ApplicationThread的bindApplication()方法。
thread.bindApplication(...);//4
...
}
ApplicationThread
public final void bindApplication(...) {
AppBindData data = new AppBindData();
...
sendMessage(H.BIND_APPLICATION, data);//5
}
ActivityThread.java
private class H extends Handler {
...
public static final int BIND_APPLICATION = 110;
...
public void handleMessage(Message msg) {
switch (msg.what) {
...
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);//6
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
}
}
private void handleBindApplication(AppBindData data) {
// 以下两个方法都是设置进程名称
Process.setArgV0(data.processName);
//可以通过反射DdmHandleAppName类中的getAppName方法获取进程名称
android.ddm.DdmHandleAppName.setAppName(data.processName,UserHandle.myUserId());
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
//创建app运行时的上下文对象,并对其进行初始化.
final ContextImpl appContext = new ContextImpl();
appContext.init(data.info, null, this);
//这里的data.info是LoadedApk类的对象
//在这里创建了上层开发者的代码中所涉及的Applicaiton类的对象
Application app = data.info.makeApplication(data.restrictedBackupMode, null);//7
...
//如果有ContentProvider的话, 先加载ContentProvider,后调用Application的onCreate()方法
List<ProviderInfo> providers = data.providers;
if (providers != null) {
installContentProviders(app, providers);
}
//调Application的生命周期函数 onCreate()
mInstrumentation.callApplicationOnCreate(app);
}
LoadedApk.java
public final class LoadedApk {
...
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
Application app = null;
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);//8
return app;
}
...
}
Instrumentation.java
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance();//9
app.attach(context);
return app;
}
不要在Android的Application对象中缓存数据!
-
不要在Application对象中缓存数据化,这有可能会导致你的程序崩掉。请使用Intent在各组件之间传递数据,抑或是将数据存储在磁盘中,然后在需要的时候取出来。
-
并不仅仅只有Application对象是这样的,其它的单例或者公有静态类也有可能会由于系统内存而被杀掉,谨记。