Android Application的高级用法及源码分析

        对于Android开发的人来说,对Application这个类肯定是不陌生的,我们一般会在这个类中去初始化一些需要在Activity启动之前初始化的资源,或是配置一些整个应用需要用到的东西,虽说用的多,但你不一定对这个类很了解,相信这篇文章肯定会让你对Application有一个全新的认识的。

        这里先提两个需要实现的要求,看看你有没有想法:

        1、监听每个Activity的生命周期(你可能会想到使用BaseActivity去监听);

        2、在应用的内存吃紧时,如何根据内存吃紧的等级去释放相应Activity的资源,不至于让应用被销毁;

        对于上述的三个需求,如果你对Application比较了解的话,那这对你来说应该就很简单了,需求是实现了,那你对Application是怎么实现的是否了解,如果不了解话,那就继续玩下看:

        首先来看看Appcation是何时在哪里创建的,在说这个这个之前,你的先知道一个类ActivityThread,Activity生命周期的各个方法就是从这里传递下去的,一个应用的启动最先执行的main方法也是在这里,当然这里控制Activity生命周期的也是远程的ActivityManagerService,这里就不涉及了,这里我们主要是从ActivityThread这里入手,一个应用最先启动调用的也是startActivity(),经过一系列的调用后会执行到ActivityThread的scheduleLaunchActivity()这个方法,所以这里就是我们的切入点,来看下这个方法:

@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                                         ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                                         CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                                         int procState, Bundle state, PersistableBundle persistentState,
                                         List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                                         boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

    ......//省略的是对一些参数的赋值操作

    sendMessage(H.LAUNCH_ACTIVITY, r);
}
private void sendMessage(int what, Object obj) {
    sendMessage(what, obj, 0, 0, false);
}
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
    ......
    mH.sendMessage(msg);
}

主要是对传过来的进行接收,然后使用Handler进行发送消息,接下来就是找到处理这条消息的地方:

public void handleMessage(Message msg) {
    if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
    switch (msg.what) {
        case LAUNCH_ACTIVITY: {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
            final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

            r.packageInfo = getPackageInfoNoCheck(
                    r.activityInfo.applicationInfo, r.compatInfo);
            handleLaunchActivity(r, null);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
        break;
        ......
    }
}

看到这里有一个方法handlerLaunchActivity(),这里方法就是处理启动Activity,到目前为止,还没看到创建Application的地方,那就继续往下找:

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ......
    //这个方法里就是执行启动activity的逻辑
    Activity a = performLaunchActivity(r, customIntent);
    ......
}

还得跟进去看下performLaunchActivity()这个方法:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                Context.CONTEXT_INCLUDE_CODE);
    }

    ComponentName component = r.intent.getComponent();
    if (component == null) {
        component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
        r.intent.setComponent(component);
    }

    if (r.activityInfo.targetActivity != null) {
        component = new ComponentName(r.activityInfo.packageName,
                r.activityInfo.targetActivity);
    }

    Activity activity = null;
    try {
        //这里是利用反射的方式创建Activity,component这个对象就包含了所需创建Activity的信息
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        r.intent.prepareToEnterProcess();
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                    "Unable to instantiate activity " + component
                            + ": " + e.toString(), e);
        }
    }

    try {
        //直到这里只是创建了Activity对象,但并没有执行Activity的任何方法,
        //下面这个方法就是去创建Application
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);

        if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
        if (localLOGV) Slog.v(
                TAG, r + ": app=" + app
                        + ", appName=" + app.getPackageName()
                        + ", pkg=" + r.packageInfo.getPackageName()
                        + ", comp=" + r.intent.getComponent().toShortString()
                        + ", dir=" + r.packageInfo.getAppDir());
        //上面通过反射的方式已经拿到了activity,这里一般不为null
        if (activity != null) {
            Context appContext = createBaseContextForActivity(r, activity);
            CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
            Configuration config = new Configuration(mCompatConfiguration);
            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                    + r.activityInfo.name + " with config " + config);
            // 这里执行Activity的attach()方法,并且会把application传过去,也就是说每
            // 个activity对持有Application对象
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor);

            if (customIntent != null) {
                activity.mIntent = customIntent;
            }
            r.lastNonConfigurationInstances = null;
            activity.mStartedActivity = false;
            int theme = r.activityInfo.getThemeResource();
            if (theme != 0) {
                activity.setTheme(theme);
            }

            activity.mCalled = false;
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                //执行到这里,最终调用到的就是Activity的onCreate()方法
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            if (!activity.mCalled) {
                throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                                " did not call through to super.onCreate()");
            }
            r.activity = activity;
            r.stopped = true;
            if (!r.activity.mFinished) {
                activity.performStart();
                r.stopped = false;
            }
            if (!r.activity.mFinished) {
                if (r.isPersistable()) {
                    if (r.state != null || r.persistentState != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                r.persistentState);
                    }
                } else if (r.state != null) {
                    mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                }
            }
            if (!r.activity.mFinished) {
                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnPostCreate(activity, r.state,
                            r.persistentState);
                } else {
                    mInstrumentation.callActivityOnPostCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                                    " did not call through to super.onPostCreate()");
                }
            }
        }
        r.paused = true;

        mActivities.put(r.token, r);//这里是将启动的Activity收集起来,后面内存吃紧时会用到

    } catch (SuperNotCalledException e) {
        throw e;

    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                    "Unable to start activity " + component
                            + ": " + e.toString(), e);
        }
    }

    return activity;
}

这个方法有点长,但主要的逻辑都在这里,所有也就没有省略,感兴趣的可以好好看下,我们这里跟着的主线是Application,所以接下来看的就是LoadedApk这个类的makeApplication()了,看名字就知道这里是创建Application了:

public Application makeApplication(boolean forceDefaultAppClass,
                                   Instrumentation instrumentation) {
    // 我们一般都说一个应用只有一个Application,看到这是不是就明白了,
    // application就是一个单列,只用在第一个activity执行到这里才会去创建Application,
    // 其他的activity都是直接返回已经创建的对象
    if (mApplication != null) {
        return mApplication;
    }

    Application app = null;

    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application";
    }

    try {
        java.lang.ClassLoader cl = getClassLoader();
        if (!mPackageName.equals("android")) {
            initializeJavaContextClassLoader();
        }
        //都说context的数量等于activity的数量加上application的数量,从这里你就会发现,
        // 在创建application的时候传进去了一个ContextImpl,
        // newApplication()方法中就是在创建application,在创建完后会执行application的attach()方法
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
        if (!mActivityThread.mInstrumentation.onException(app, e)) {
            throw new RuntimeException(
                    "Unable to instantiate application " + appClass
                            + ": " + e.toString(), e);
        }
    }
    //将创建的application添加到ActivityThread一个存集合中
    mActivityThread.mAllApplications.add(app);
    mApplication = app;

    if (instrumentation != null) {
        try {
            //下面这个方法最终会执行到Application的onCreate()方法
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            if (!instrumentation.onException(app, e)) {
                throw new RuntimeException(
                        "Unable to create application " + app.getClass().getName()
                                + ": " + e.toString(), e);
            }
        }
    }

    // Rewrite the R 'constants' for all library apks.
    SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
            .getAssignedPackageIdentifiers();
    final int N = packageIdentifiers.size();
    for (int i = 0; i < N; i++) {
        final int id = packageIdentifiers.keyAt(i);
        if (id == 0x01 || id == 0x7f) {
            continue;
        }

        rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
    }

    return app;
}

makeApplication()主要就是创建Application,如果Application存在那就直接放回,一般是在启动第一个Activity的时候才会创建Application,其他的时候都是直接返回了,这里可以把application理解为单例。

        到这里,Application的创建已经分析完了,接下来就是分析该如何去实现上面所说的需求了,这里我们可以去推测一下,首先是第一个需求:

        1、监听每个Activity的生命周期(你可能会想到使用BaseActivity去监听);既然要监听每个activity的对应生命周期,那么 就需要在Application中去维护一个与Activity生命周期对应的方法,当执行Activity生命周期方法的时候调用Application对应的方法,那到底是不是呢?那就去看看源码了:

        (1)根据上面的分析,首先去验证的就是去Application中看看有没有对应的生命周期方法:

public interface ActivityLifecycleCallbacks {
    void onActivityCreated(Activity activity, Bundle savedInstanceState);
    void onActivityStarted(Activity activity);
    void onActivityResumed(Activity activity);
    void onActivityPaused(Activity activity);
    void onActivityStopped(Activity activity);
    void onActivitySaveInstanceState(Activity activity, Bundle outState);
    void onActivityDestroyed(Activity activity);
}

一看就是跟Activity中的生命周期有对应。

        (2)接下来就是去Activity的生命周期方法中查看是不是有调用Application中相对应的方法了:

protected void onCreate(@Nullable Bundle savedInstanceState) {
    ......
    //这里调用到了Application的dispatchActivityCreated()
    getApplication().dispatchActivityCreated(this, savedInstanceState);
    ......
}
public final Application getApplication() {
    return mApplication;
}
//在ActivityThread中创建完Application后执行的Activity的attach()方法就把Application传过来了
final void attach(Context context, ActivityThread aThread,
                  Instrumentation instr, IBinder token, int ident,
                  Application application, Intent intent, ActivityInfo info,
                  CharSequence title, Activity parent, String id,
                  NonConfigurationInstances lastNonConfigurationInstances,
                  Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
    ......
    mApplication = application;
    ......
}

每个Activity的onCreate()方法中都会调用到Application的dispatchActivityCreate()方法,这里还得去看看这个方法的实现:

/* package */ void dispatchActivityCreated(Activity activity, Bundle savedInstanceState) {
    Object[] callbacks = collectActivityLifecycleCallbacks();
    if (callbacks != null) {
        for (int i=0; i<callbacks.length; i++) {
            ((ActivityLifecycleCallbacks)callbacks[i]).onActivityCreated(activity,
                    savedInstanceState);
        }
    }
}

这里执行的就是(1)中接口的方法,接下就该思考这个接口是如何添加到集合中去的了,看collectActivityLifcycleCallbacks():

private Object[] collectActivityLifecycleCallbacks() {
    Object[] callbacks = null;
    synchronized (mActivityLifecycleCallbacks) {
        if (mActivityLifecycleCallbacks.size() > 0) {
            callbacks = mActivityLifecycleCallbacks.toArray();
        }
    }
    return callbacks;
}

这个方法里还是挺简单的,实际返回的还是mActivityLifecycleCallback这个集合中内容,接下来就是去找下将数据添加到这个集合中的方法了:

public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
    synchronized (mActivityLifecycleCallbacks) {
        mActivityLifecycleCallbacks.add(callback);
    }
}

到这里一切就都连接上了,实现上面的接口,然后调用这个方法,那么每个Activity对应的生命周期就都会执行这个接口中的对应方法了,这里只是跟着onCreate()的方法走了一遍,其他的方法类似,这里就不重复了。

        这个方法有很多地方都可以用到,就看你去怎么用了。这里的一个简单使用就Activity的栈管理了,感兴趣的可以看下自动维护一个Activity栈管理,这样,第一点就就讲到这里了。

        2、在应用的内存吃紧时,如何根据内存吃紧的等级去释放相应Activity的资源,不至于让应用被销毁;

        在系统内存吃紧时,会优先杀死占用资源比较多的应用,这个时候就需要我们去释放资源来防止应用被杀死,在应用内存吃紧时会执行ActivityThread的scheduleTrimMemory()来通知应用该释放资源:

public void scheduleTrimMemory(int level) {
    sendMessage(H.TRIM_MEMORY, null, level);
}
public void handleMessage(Message msg) {
    if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
    switch (msg.what) {
        ......
        case TRIM_MEMORY:
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "trimMemory");
            handleTrimMemory(msg.arg1);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            break;
        .......
    }
}
final void handleTrimMemory(int level) {
    if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level);
    //这里应该知道Activity是实现了ComponentCallbacks2这个接口的,其实这里就是收集Application、Activity和Service
    ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
    
    final int N = callbacks.size();
    for (int i = 0; i < N; i++) {
        //这里就是执行Activity和Application的onTrimMemory()方法
        callbacks.get(i).onTrimMemory(level);
    }

    WindowManagerGlobal.getInstance().trimMemory(level);
}

这里先去看下Activity的onTrimMemory()方法:

public void onTrimMemory(int level) {
    if (DEBUG_LIFECYCLE) Slog.v(TAG, "onTrimMemory " + this + ": " + level);
    mCalled = true;
    //如果这个activity中包含有Fragment那么就会去执行Fragment的onTrimMemory()方法
    mFragments.dispatchTrimMemory(level);
}

然后该去看看collectComponentCallbacks()是如何收集所有的Activity、Service和Application的了:

ArrayList<ComponentCallbacks2> collectComponentCallbacks(
        boolean allActivities, Configuration newConfig) {
    ArrayList<ComponentCallbacks2> callbacks
            = new ArrayList<ComponentCallbacks2>();

    synchronized (mResourcesManager) {
        // 这里是收集Application
        // 前面在讲makeApplication()创建Application的时候有提到,
        // 创建的Application都会添加到这个集合中
        final int NAPP = mAllApplications.size();
        for (int i=0; i<NAPP; i++) {
            callbacks.add(mAllApplications.get(i));
        }
        final int NACT = mActivities.size();
        // 这里是收集Activity
        // 前面再讲performLaunchActivity()这个方法的有提到,创建的Activity都会添加到这个集合中去
        for (int i=0; i<NACT; i++) {
            ActivityClientRecord ar = mActivities.valueAt(i);
            Activity a = ar.activity;
            if (a != null) {
                Configuration thisConfig = applyConfigCompatMainThread(
                        mCurDefaultDisplayDpi, newConfig,
                        ar.packageInfo.getCompatibilityInfo());
                if (!ar.activity.mFinished && (allActivities || !ar.paused)) {
                    // If the activity is currently resumed, its configuration
                    // needs to change right now.
                    callbacks.add(a);
                } else if (thisConfig != null) {
                    // Otherwise, we will tell it about the change
                    // the next time it is resumed or shown.  Note that
                    // the activity manager may, before then, decide the
                    // activity needs to be destroyed to handle its new
                    // configuration.
                    if (DEBUG_CONFIGURATION) {
                        Slog.v(TAG, "Setting activity "
                                + ar.activityInfo.name + " newConfig=" + thisConfig);
                    }
                    ar.newConfig = thisConfig;
                }
            }
        }
        final int NSVC = mServices.size();
        // 这里是在收集Service
        for (int i=0; i<NSVC; i++) {
            callbacks.add(mServices.valueAt(i));
        }
    }
    synchronized (mProviderMap) {
        final int NPRV = mLocalProviders.size();
        for (int i=0; i<NPRV; i++) {
            callbacks.add(mLocalProviders.valueAt(i).mLocalProvider);
        }
    }

    return callbacks;
}

看到这里突然发现通过Application去管理onTrimMemory没什么用了,因为ActivityThread已经给我们做好了分发,我们只要在Activity中去实现onTrimMemory()就可以了。到这差不多完了,但是还没有,onTrimMemory()这个方法中是有参数的,我们就是根据这个参数来决定什么时候该释放什么资源:

public interface ComponentCallbacks2 extends ComponentCallbacks {

    // 应用快接近被杀死了
    static final int TRIM_MEMORY_COMPLETE = 80;

    // 应用接近被杀死的中间阶段
    static final int TRIM_MEMORY_MODERATE = 60;

    // 应用被例入可以被杀死的初始阶段,这个阶段可以开始释放一些资源了
    static final int TRIM_MEMORY_BACKGROUND = 40;

    // 应用的所有界面处于后台了,这个时候你可以释放一些不太需要的资源
    static final int TRIM_MEMORY_UI_HIDDEN = 20;

    //以下三个是应用程序处于前台,且都可以正常运行
    //内存有点低了,系统可能会去杀死一些进程
    static final int TRIM_MEMORY_RUNNING_CRITICAL = 15;

    //内存更低了,有些应用程序已经被杀死了
    static final int TRIM_MEMORY_RUNNING_LOW = 10;
    
    //内存已经非常的低了,大部分应用程序已经被杀死了
    static final int TRIM_MEMORY_RUNNING_MODERATE = 5;
    
    void onTrimMemory(int level);
}

到这Application就差不多整体梳理了一遍,这里在总结一下:

        1、Application是在Activity反射实例化之后,生命周期方法执行之前实例化的;

        2、在拿Application的实例之前会进行判断是否已经存在实例,存在就直接返回,可以看做是一个单列;

        3、在执行Activity的attach()时,会把Application实例传过去,也就说每个Activity都拥有同一个Application实例;

        4、一个应用存在多个进程的时候,这个时候Application是存在多个实例的;

        5、系统内存吃紧时应该根据系统传过来的状态对相应的资源进行释放。




猜你喜欢

转载自blog.csdn.net/tangedegushi/article/details/80775322