Application的总结

456 阅读2分钟

Application有什么作用?

  1. 保存应用进程内的全局变量。
  2. 初始化资源。
  3. 提供应用上下文。

注意点:

应用启动时会在Application的onCreate()方法中初始化一些全局资源,系统配置,三方sdk等。此处需要注意一点,App可能会有多个进程:主进程、三方sdk的一些进程,初始sdk的时候需要注意在相应的进程中去初始化,避免浪费资源。

Application的生命周期

  1. 构造函数
  2. attachBaseContext
  3. 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对象是这样的,其它的单例或者公有静态类也有可能会由于系统内存而被杀掉,谨记。

参考