• get****Context各个方法分析


    1 getApplicationContext分析

    该方法为contextImpl类的方法,返回一个ApplicationContext。方法代码为:

    public Context getApplicationContext() {

            return (mPackageInfo != null) ?

                    mPackageInfo.getApplication() : mMainThread.getApplication();

        }

    1.1 mPackageInfo.getApplication()分析

    如果mPackeageInfo对象(LoadedApk类,全局唯一)不为空,就调用mPackageInfo的getApplication方法。该方法返回mPackageInfo对象中的mApplication对象。LoadedApk类中的mApplication只在一个地方被赋值:

    public Application makeApplication(boolean forceDefaultAppClass,

                Instrumentation instrumentation) {

            if (mApplication != null) {

                return mApplication; //如果mApplication不为空,就直接返回该值,说明android只允许一个APK含有一个application对象

            }

            //否则就创建一个Application对象

    Application app = null;

            String appClass = mApplicationInfo.className;

            if (forceDefaultAppClass || (appClass == null)) {

    //如果app类名为空,或者指定要求使用默认app类名,就使用这个类名

                appClass = "android.app.Application";

            }

    //开始新建一个application对象

            try {

                java.lang.ClassLoader cl = getClassLoader();

               //首先创建一个ContextImpl对象

                ContextImpl appContext = new ContextImpl();

                appContext.init(this, null, mActivityThread); //初始化

                app = mActivityThread.mInstrumentation.newApplication(

                        cl, appClass, appContext);

                appContext.setOuterContext(app);

            } catch (Exception e) {

               ……

    }

    //将此app加入到mAllApplications链表中

            mActivityThread.mAllApplications.add(app);        

    mApplication = app; //这里完成给mApplication赋值

            …….              

            return app;

        }

    通过上面的分析,可以知道mPackageInfo.getApplication()方法返回当前APK的唯一的Application对象。

    1.2 mMainThread.getApplication()分析

    如果mPackeageInfo对象为空,就调用此方法。关于mPackeageInfo相关知识,目前还没分析透,待分析完全之后补充。

    mMainThread为ActivityThread类,所以我们需要去ActivityThread.java中找寻答案。该类的getApplication方法返回mInitialApplication对象,此对象也是Application类。同样的分析方法,我们去探寻该对象是如何被赋值的。

    在ActivityThread类中共有两个地方对其进行了赋值,第一处的代码如下:

    private void handleBindApplication(AppBindData data) {

    ……

    try {

     // If the app is being launched for full backup or restore, bring it up in

     // a restricted environment with the base application class.

       Application app = data.info.makeApplication(data.restrictedBackupMode, null);

       mInitialApplication = app;
        }

    ……

    }

    显然mInitialApplication对象是通过makeApplication方法创建的,所以这里的mInitialApplication与mPackageInfo.getApplication()方法返回的Application是同一个对象。同时需要说明一下handleBindApplication函数。该函数会在应用程序第一次启动时调用。具体点说就是:在启动应用程序时ActivityManagerService类中的onTranct方法会调用ActivityThread.bindApplication方法,此方法有两种参数(一为applicationInfo,二为其他相关函数);在bindApplication中会根据这两种参数构建一个AppBindData对象data,然后以此对象为参数调用sendMessage(int what = H.BIND_APPLICATION, Object m = data;过后系统就会在消息处理函数ActivityThread.handleMessage(int what)中调用handleBindApplication(AppBindData data)创建ApplicationContext对象。

    另一处的代码如下:

    private void attach(boolean system) {

        if (!system) {

                ……

        } else {//如果是系统进程,那么就调用以下代码

                // Don't set application object here -- if the system crashes,

                // we can't display an alert, we just want to die die die.

           android.ddm.DdmHandleAppName.setAppName("system_process",

    UserHandle.myUserId());

                try {

                    mInstrumentation = new Instrumentation();

                    ContextImpl context = new ContextImpl();

                    context.init(getSystemContext().mPackageInfo, null, this);

                    Application app = Instrumentation.newApplication(Application.class, context);

                    mAllApplications.add(app);

                    mInitialApplication = app;

                    app.onCreate();

                } catch (Exception e) {

                    throw new RuntimeException(

                            "Unable to instantiate Application():" + e.toString(), e);

                }

        }

    }

    对比此处红色部分的代码,和上面makeApplication方法的代码,可以发现两者其实都是创建一个Application对象。不过attach方法只在FrameWork进程(system_server)启动时调用,应用程序运行时并不会调用此方法。所以这里可以忽略。

    总之,对应用程序而言getApplicationContext方法返回的都是应用程序的唯一ApplicationContext。

    2 getBaseContext分析

    此方法在ContextWrapper类中定义。代码如下:

    public Context getBaseContext() {

            return mBase;

    }

    这里的mBase就是一个Context对象,getBaseContext() 返回由ContextWrapper类的构造函数指定或attachBaseContext ()设置的Context,SDK文档很少,不推荐使用。

    3 Activity.this分析

    Activity.this返回当前activity的context,这个context属于当前的activity,会随着activity的摧毁而摧毁。

    4 getContext

    该方法比较特殊,特殊的原因不是它复杂,而是它的不确定性。因为并不是每一个类都有该方法,也不是每一个类中该方法的作用均相同。如在android.view类,它就返回当前view所运行的context,一般情况下是当前的activity的context。而在contentProvider类中,该方法返回的是ApplicationContext(在ActivityThread.installProvider中可以知道)。所以该方法的返回值要根据具体情况具体分析。

    总结

    了解了所有的获取context相关的函数过后,我们就可以很容易的理解下面的问题了:

    this: 当前activity的context,生命周期为当前activity的生命周期。

    This.getApplicationContext:返回整个应用程序的application context,生命周期为整个应用程序。

  • 相关阅读:
    go语言从零学起(三) -- chat实现的思考
    go语言从零学起(二)--list循环删除元素(转载)
    go语言从零学起(一) -- 文档教程篇
    Spring框架事务支持模型的优势
    Thymeleaf
    社保到底是多交好,还是少交好?
    使用静态工厂方法而不是构造器
    EJB、RMI、XMLRPC、Hessian、Thrift 、Protobuf
    MySQL存储过程
    MySQL常用功能语句分类总结
  • 原文地址:https://www.cnblogs.com/wanyuanchun/p/3828603.html
Copyright © 2020-2023  润新知