Android架构师-Android中的Context-初步分析Android中Context的实现-装饰者模式

尊重原创:https://blog.csdn.net/abm1993/article/details/82968235

说到Context,大家一定非常熟悉,Android中的很多操作都和Context有关,比如打开activity、发送广播、打开本包下文件夹和数据库、获取classLoader、获取资源等等。那么这个Context究竟是何方神圣,我们不得而知,仅仅止步于如何使用Context,本篇将和大家一起聊聊Android中的Context。

首先我们先来了解装饰者模式是什么样的

装饰模式的思想是在不改变原来类文件和使用继承的情况下动态的扩展类的功能

 

Context架构设计

abm

Android Context的设计完美的体现了装饰模式,装饰模式的思想是在不改变原来类文件和使用继承的情况下动态的扩展类的功能。Context就是一个抽象接口,ContextImpl是该接口的实现,而ContextWrapper就是装饰者,Application,Service等等就是更加具体的装饰者。而这些接口实现和装饰者在Android中是如何联系在一起的呢?我们继续往下分析。

创建Context

我们知道有很多操作都依赖Context,比如启动Activity,启动Service……那么这些Context是在什么时候创建的呢?ActivityThread的main函数是应用程序的入口,我们就从main函数开始分析:

    public static void main(String[] args) {
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

继续看下ActivityThread的attach方法:

    private void attach(boolean system, long startSeq) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ViewRootImpl.addFirstDrawHandler(new Runnable() {
                @Override
                public void run() {
                    ensureJitEnabled();
                }
            });
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManager.getService();
            try {
//作用在于将mAppThread传递到AMS进程去,最后在AMS的attachApplicationLocked
//方法中会调用mAppThread的bindApplication方法
                mgr.attachApplication(mAppThread, startSeq);

            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        } else {//系统进程,暂不分析
        }
    }

根据分析,继续查看ApplicationThread的bindApplication方法,这里就不一一罗列代码了直接查看最终调用处理的handleBindApplication方法:

    private void handleBindApplication(AppBindData data) {
        long st_bindApp = SystemClock.uptimeMillis();
        // Note when this process has started.
        Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
        // send up app name; do this *before* waiting for debugger
        Process.setArgV0(data.processName);
        android.ddm.DdmHandleAppName.setAppName(data.processName,
                                                UserHandle.myUserId());
        VMRuntime.setProcessPackageName(data.appInfo.packageName);
 
        data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);//创建LoadedApk,LoadedApk就是Apk文件在内存中的表示
 
        try {
            app = data.info.makeApplication(data.restrictedBackupMode, null);//为应用创建Application
            mInitialApplication = app;
            try {
                mInstrumentation.callApplicationOnCreate(app);//调用Application的onCreate方法
            } catch (Exception e) {
            }
        } finally {
        }
    }

继续看下LoadedApk的makeApplication方法:

    public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        Application app = null;
        try {
            java.lang.ClassLoader cl = getClassLoader();
            if (!mPackageName.equals("android")) {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        "initializeJavaContextClassLoader");
                initializeJavaContextClassLoader();
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;
        return app;
    }
 
    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = getFactory(context.getPackageName())
                .instantiateApplication(cl, className);
        app.attach(context);
        return app;
    }
 
    final void attach(Context context) {
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
    }
 
    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

终于守得云开见月明,终于在makeApplication看见创建ContextImpl,从Context架构设计一节中我们知道Application是一个装饰者,用来装饰谁呢?Context的实现类ContextImpl。当我们创建完Application时,此时Application中的mBase指向的就是我们通过createAppContext,其赋值的地方就是app.attach(context)。同时ContextImpl也通过设置setOuterContext与Application关联。同样的我们创建Activity和Service的时候也会创建对应的ContextImpl并且设置与ContextImpl关联。那么他们设置的关联有什么作用呢?答案肯定是有的,当我们在Activity中或者Application或者Service中或者调用某个Context的getBaseContext方法的时候,获取的便是这个ContextImp。再来看下Activity创建过程是如何管理ContextImpl的:
 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值