A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 就业部_安卓组 于 2016-12-28 15:37 编辑
        有很多人包括我自己有种习惯,就是先存书签以后再看。为了方便各位随时随地,有网没网都可以查看,所以我在文末上传了本文完整附件下载,有需要的同学可以下载到电脑里,方便以后阅览。(快给我个好评)
        从接触 Android 开始,就一直被一个既陌生又熟悉的单词所围绕,那就是 Context。

        无论你是第一次接触 Android 的菜鸟,还是开发中的老鸟,你对 Context 的使用一定不陌生,因为它太常见了,你在加载资源、开启 Activity、创建 View等等都需要 Context。但是 Context 到底是什么呢?一个应用程序中到底有多少个 Context 呢?在什么场景下使用不同的 Context?下面讲一一解答大家的疑惑。

Context 是什么?
        
        Context ,字面意思上理解是上下文,它贯穿了整个应用。
        它是一个运行环境,提供了一个应用运行所需要的信息,资源,服务等。
        它是一个场景,用户操作和系统交互这一过程就是一个场景,比如 Activity 之间的切换,Service 的启动等。

        官方 SDK 中对其描述如下:

       Interface to global information about anapplication environment. This is an abstract class whose implementation isprovided by the Android system. It allows access to application-specificresources and classes, as well as up-calls for application-level operationssuch as launching activities, broadcasting and receiving intents, etc.

        根据描述我们可以得到如下信息:
                 它说 Context 所描述的是一个应用程序环境的信息,即上下文;
                 这是一个抽象类,Android 系统提供了具体实现类;
                 可以通过它获取应用的 resources 和 classes,也包括一些应用级别操作,比如:启动 Activity,发送广播,接收 intent 信息等等

        这些太抽象了,究竟 Context 是什么?我们平常所说的 Activity、Application、Service其实统统都是一个 Context。
        我们去看一下类的继承关系:


        发现 Activity、Service、Application都是 Context 的子类。
        Context 是一个抽象类,而上述的都是该类的一个实现。Service 和 Application 以及 ContextThemeWrapper 统一继承自 ContextWrapper ,而我们的 Activity 继承自 ContextThemeWrapper,要搞清楚这个类继承的关系。
        一张图表示他们的关系


类的剖析

        首先要了解一下这几个类是做什么的,查看源代码(基于API 23)下。
        Context 类的源代码 3814 行(API 23),贴出来部分给大家看一下:

Context

[Java] 纯文本查看 复制代码
public abstract class Context{
    ...
    // 启动 Activity
    public abstract void startActivity(Intentintent);
    // 获取系统服务
    public abstract Object getSystemService(Stringname);
    // 发送广播
    public abstract void sendBroadcast(Intentintent);
    // 开启 Service
    public abstract ComponentName startService(Intentservice);

    public abstract AssetManager getAssets();

    public abstract Resources getResources();

    public abstract PackageManager getPackageManager();
    ...
}

        源码看到 Context 是一个抽象类,里面定义了各种各样的抽象方法,诸如获取资源,启动 Activity、Service,发送广播,操作数据库,弹出 Toast 等都需要用到 Context 。所以可以理解为 Context 就是抽象出一个 App 应用所有功能的集合,它的具体方法实现是在类 ContextImpl 中实现的。


ContextImpl
[Java] 纯文本查看 复制代码
class ContextImpl extends Context {
    //整个App的主线程
    final ActivityThread mMainThread;
    //整个App的相关信息
    final LoadedApk mPackageInfo;
    //资源解析器
    private final ResourcesManagermResourcesManager;
    //App资源类
    private final Resources mResources;
    //外部Context的引用
    private Context mOuterContext;
    //默认主题
    private int mThemeResource = 0;
    private Resources.Theme mTheme = null;
    //包管理器
    private PackageManagermPackageManager;
    ...
    //以下是静态区注册系统的各种服务,多达五六十种系统服务,因此每个持有Context引用的对象都可以随时通过getSystemService方法来轻松获取系统服务。
    static {
      registerService(ACCESSIBILITY_SERVICE, new ServiceFetcher() {
           public Object getService(ContextImplctx) {
                returnAccessibilityManager.getInstance(ctx);
            }});

       registerService(CAPTIONING_SERVICE, new ServiceFetcher() {
           public Object getService(ContextImplctx) {
                return newCaptioningManager(ctx);
            }});

        registerService(ACCOUNT_SERVICE, newServiceFetcher() {
            public Object createService(ContextImplctx) {
                   IBinder b =ServiceManager.getService(ACCOUNT_SERVICE);
                   IAccountManager service =IAccountManager.Stub.asInterface(b);
                   return newAccountManager(ctx, service);
               }});
    ...

   }

    ...
    //启动Activity的地方
     @Override
     public void startActivity(Intent intent,Bundle options) {
           warnIfCallingFromSystemProcess();
            if((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
                throw newAndroidRuntimeException(
                "CallingstartActivity() from outside of an Activity " + 
                " context requiresthe FLAG_ACTIVITY_NEW_TASK flag." + 
                " Is this reallywhat you want?");
            }
           mMainThread.getInstrumentation().execStartActivity(
                getOuterContext(),mMainThread.getApplicationThread(), null,
                (Activity)null, intent, -1,options);
        }
    ...
//启动服务的地方
    @Override
    public ComponentName startService(Intentservice) {
            warnIfCallingFromSystemProcess();
            return startServiceCommon(service,mUser);
    }
    ... 
}

        ContextImpl 实现了抽象类 Context 里面的所有方法,而又因为Context 的具体能力是由 ContextImpl 类来实现,也就是说像 Activity、Application 这样的类其实并不会去具体实现 Context 的功能,仅仅只是做了一层接口封装而已,Context 的具体功能都是由 ContextImpl 去完成的。因此绝大多数情况下,Activity、Service、Application 这三种类型的 Context 是可以通用的。但是,有几种情况比较特殊,比如启动 Activity,弹出 Dialog。出于安全原因的考虑, Android 是不允许 Activity 或 Dialog 凭空出现的,例如 Activity 的启动是必须要建立在另一个 Activity 的基础之上,以此形成返回栈。而 Dialog 则必须在一个 Activity上面弹出(除非是System Alert类型的 Dialog),因此在这种情况下,我们只能使用 Activity 类型的 Context,否则就会出错。


ContextWrapper

        ContextWrapper 是 Context 的子类,名字上我们可以看到是 Context 的包装,Application、Activity、Service 都是直接或间接继承自 ContextWrapper,点开 ContextWrapper

[Java] 纯文本查看 复制代码
public class ContextWrapper extends Context{

    Context mBase;
    // 给mBase赋值
    public ContextWrapper(Context base){

        mBase = base;
    }
    // 创建Application、Service、Activity的时候会调用该方法,给mBase赋值,若mBase早已赋值,会抛出状态非法异常
    protected void attachBaseContext(Contextbase) {

        if(mBase != null) {
            throw newIllegalStateException("mBase context already set");
            mBase = base;
        }
    }
    ...
    public Context getBaseContext() {  
        return mBase;  
    } 

    @Override  
    public AssetManager getAssets() {  
        return mBase.getAssets();  
    } 

    @Override  
    public Resources getResources() {  
        return mBase.getResources();  
    } 

    @Override  
    public ContentResolver getContentResolver(){  
        return mBase.getContentResolver();  
    } 

    @Override  
    public Looper getMainLooper() {  
        return mBase.getMainLooper();  
    } 

    @Override  
    public Context getApplicationContext(){  
        return mBase.getApplicationContext();  
    } 

    @Override  
    public String getPackageName() {  
        return mBase.getPackageName();  
    } 

    @Override  
    public void startActivity(Intentintent) {  
        mBase.startActivity(intent);  
    } 

    @Override  
    public void sendBroadcast(Intentintent) {  
        mBase.sendBroadcast(intent);  
    } 

    @Override  
    public Intent registerReceiver(  
        BroadcastReceiver receiver,IntentFilter filter) {  
        return mBase.registerReceiver(receiver,filter);  
    } 

    @Override  
    public void unregisterReceiver(BroadcastReceiverreceiver) {  
       mBase.unregisterReceiver(receiver); 
    }  

    @Override  
    public ComponentName startService(Intentservice) {  
        return mBase.startService(service);  
    } 

    @Override  
    public boolean stopService(Intentname) {  
        return mBase.stopService(name);  
    } 

    @Override  
    public boolean bindService(Intentservice, ServiceConnection conn,  
            int flags) {  
        return mBase.bindService(service,conn, flags);  
    } 

    @Override  
    public void unbindService(ServiceConnectionconn) {  
        mBase.unbindService(conn);  
    } 

    @Override  
    public Object getSystemService(Stringname) {  
        return mBase.getSystemService(name);  
    } 
    ...
}

        如上。

        很多方法都是比较常见的。首先可以看到所有的方法具体的实现都是统一调用 mBase 对象中对应的当前方法名的方法。
        那何为 mBase?
        注意看 attachBaseContext() 这个方法,此方法传入了一个 base 参数,并将它赋值给 mBase 对象。
        而 attachBaseContext() 这个方法其实是由系统来调用的,当我们创建 Activity、Service、Application时就会调用该方法,它会把 ContextImpl 对象作为参数传递到 attachBaseContext() 方法当中,从而赋值给 mBase 对象,之后 ContextWrapper 中的所有方法其实都是通过这种委托的机制交由 ContextImpl 去具体实现的,所以说 ContextImpl 是上下文功能的实现类。
        而 getBaseContext() 方法,返回了mBase 对象,其实这个对象就是 ContextImpl 对象。

ContextThemeWrapper

        而 ContextThemeWrapper 类,意味着该类内部包含了 Theme 相关的接口,也就是 android:theme 属性所指定的。我们都知道,只有 Activity 才需要主题,Service 是不需要主题的,Activity 在启动的时候系统都会加载一个主题,也就是我们平时在 AndroidManifest.xml 文件里面写的 android:theme=”@style/AppTheme“ 属性。因此 Activity 继承自ContextThemeWrapper ,Service 和Application 继承自 ContextWrapper,而 ContextThemeWrapper 也继承自 ContextWrapper。
所以Activity,Application,Service 其实都关联着一个 mBase 变量,而 mBase 变量是 ContextImpl 对象的赋值,也是真正实现抽象类 Context 的地方。虽然 Activity,Application,Service 都统一继承自 Context,但是他们自己本身持有的 Context 对象是不同的。

        查看 ContextThemeWrapper 的部分源代码:

[Java] 纯文本查看 复制代码
public class ContextThemeWrapper extends ContextWrapper{

    private int mThemeResource;
    private Resources.Theme mTheme;
    private LayoutInflater mInflater;
    private ConfigurationmOverrideConfiguration;
    private Resources mResources;

    public ContextThemeWrapper() {
        super(null);
    }

    public ContextThemeWrapper(Contextbase, @StyleRes int themeResId) {
        super(base);
        mThemeResource = themeResId;
    }

    public ContextThemeWrapper(Contextbase, Resources.Theme theme) {
        super(base);
        mTheme = theme;
    }

    @Override
    protected void attachBaseContext(ContextnewBase) {
        super.attachBaseContext(newBase);
    }

}

Context 创建的时机

        知道了 Context 的继承关系后,自然而然的就想到什么时候会创建 Context 对象呢?
        应用程序创建 Context 时的情况有这么几种情况:
                创建 Application 时
                创建 Service 时
                创建 Activity 时

Application 的创建

        每个应用程序第一次启动的时候,都会首先创建 Application 对象。创建 Application 的时机在创建 handleBindApplication() 方法中,位于 ActivityThread中,如下:

[Java] 纯文本查看 复制代码
//创建Application时同时创建的ContextIml实例  
private final void handleBindApplication(AppBindData data){  
    ... 
    ///创建Application对象  
    Application app = data.info.makeApplication(data.restrictedBackupMode,null);  
    ... 
}  

public Application makeApplication(boolean forceDefaultAppClass,Instrumentation instrumentation) {  
    ... 
    try { 
        java.lang.ClassLoader cl =getClassLoader();  
        //创建一个ContextImpl对象实例  
        ContextImpl appContext = newContextImpl();  
        //初始化该ContextIml实例的相关属性   
        appContext.init(this, null,mActivityThread);  
        ///新建一个Application对象   
        app = mActivityThread.mInstrumentation.newApplication(  
                cl, appClass,appContext);  
        //将该Application实例传递给该ContextImpl实例                    
        appContext.setOuterContext(app); 
    }  
    ... 
}  

        通过 makeApplication 方法创建一个 Application 对象,在 makeApplicatioin 方法中,创建一个 ContextImpl 对象的实例并初始化相关属性,然后通过 ActivityThread 的 Instrumentation 对象调用 newApplication 方法得到该 Application 对象。

Activity 的创建

        当我们每次启动 Activity 的时候,看源代码:

[Java] 纯文本查看 复制代码
Override
public void startActivity(Intent intent, @Nullable Bundle options) {
   if (options != null) {
        startActivityForResult(intent, -1,options);
    } else {
        // Note we want to go through this call forcompatibility with
        // applications that may haveoverridden the method.
        startActivityForResult(intent, -1);
    }
}

        可以看到,都会走到 startActivityForResult 中去,而查阅startActivityForResult 的源码:

[Java] 纯文本查看 复制代码
public void startActivityForResult(@RequiresPermissionIntent intent, int requestCode,@Nullable Bundle options) {
    if (mParent == null) {
        Instrumentation.ActivityResult ar=
           mInstrumentation.execStartActivity(
                this,mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode,options);
        if (ar != null) {
           mMainThread.sendActivityResult(
                mToken, mEmbeddedID,requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        if (requestCode >= 0) {
            // If this start isrequesting a result, we can avoid making
            // the activity visible untilthe result is received.  Setting
            // this code duringonCreate(Bundle savedInstanceState) or onResume() will keep the
            // activity hidden duringthis time, to avoid flickering.
            // This can only be done whena result is requested because
            // that guarantees we willget information back when the
            // activity is finished, nomatter what happens to it.
            mStartedActivity = true;
        }

       cancelInputsAndStartExitTransition(options);
        // TODO Considerclearing/flushing other event sources and events for child windows.
    } else {
        if (options != null) {
           mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            // Note we want to go throughthis method for compatibility with
            // existing applications thatmay have overridden it.
           mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}

        通过 mInstrumentation.execStartActivity() 方法最终调用了 ActivityManagerNative.getDefault().startActivity()方法。
        而 ActivityManagerNative.getDefault() 实际是通过 Binder 机制调到了另一个进程中的AMS.startActivity 方法,然后ActivityStackSupervisor.realStartActivityLocked 等等等等一大堆,最终走到了ActivityThread.handleLaunchActivity 方法,如下:

[Java] 纯文本查看 复制代码
private void handleLaunchActivity(ActivityClientRecordr, Intent customIntent, String reason) {
    // If we are getting ready to gcafter going to the background, well
    // we are back active so skip it.
    unscheduleGcIdler();
    mSomeActivitiesChanged = true;

    if (r.profilerInfo != null) {
       mProfiler.setProfiler(r.profilerInfo);
        mProfiler.startProfiling();
    }

    // Make sure we are running with themost recent config.
    handleConfigurationChanged(null, null);

    if (localLOGV) Slog.v(
        TAG, "Handling launch of" + r);

    // Initialize before creating theactivity
    WindowManagerGlobal.initialize();

    // 在这里启动一个 Activity
    Activity a = performLaunchActivity(r,customIntent);

    if (a != null) {
        r.createdConfig = newConfiguration(mConfiguration);
        reportSizeConfigurations(r);
        Bundle oldState = r.state;
        handleResumeActivity(r.token, false,r.isForward,
                !r.activity.mFinished&& !r.startsNotResumed, r.lastProcessedSeq, reason);

        if (!r.activity.mFinished&& r.startsNotResumed) {
            // The activity manageractually wants this one to start out paused, because it
            // needs to be visible butisn't in the foreground. We accomplish this by going
            // through the normal startup(because activities expect to go through onResume()
            // the first time they run,before their window is displayed), and then pausing it.
            // However, in this case wedo -not- need to do the full pause cycle (of freezing
            // and such) because theactivity manager assumes it can just retain the current
            // state it has.
           performPauseActivityIfNeeded(r, reason);

            // We need to keep around theoriginal state, in case we need to be created again.
            // But we only do this forpre-Honeycomb apps, which always save their state when
            // pausing, so we can nothave them save their state when restarting from a paused
            // state. For HC and later,we want to (and can) let the state be saved as the
            // normal part of stoppingthe activity.
            if (r.isPreHoneycomb()) {
                r.state = oldState;
            }
        }
    } else {
        // If there was an error, for anyreason, tell the activity manager to stop us.
        try {
           ActivityManagerNative.getDefault()
                .finishActivity(r.token,Activity.RESULT_CANCELED, null,
                       Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
            throwex.rethrowFromSystemServer();
        }
    }
}

        而 handleLaunchActivity 内部又调用了 performLaunchActivity() 方法,然后去创建了一个 Activity 实例,并且回调onCreate() , onStart()方法等。

[Java] 纯文本查看 复制代码
/**
    主要做了以下几件事
    1. 从ActivityClientRecord中获取待启动act的组件信息;
    2. 通过Instrumentation.newActivity方法使用ClassLoader创建act对象;
    3. 通过LoadedApk.makeApplication方法创建Application对象,注意如果已经有Application对象的话是不会再次创建的;
    4. 创建ComtextImpl对象,并调用Activity.attach方法完成一些重要数据的初始化操作;
    5. 最终调用Activity.onCreate()方法;
*/
private Activity performLaunchActivity(ActivityClientRecord r, IntentcustomIntent) {
           //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 = newComponentName(r.activityInfo.packageName,
                  r.activityInfo.targetActivity);
       }

       Activity activity = null;
       try {
           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 newRuntimeException(
                   "Unable toinstantiate activity " + component
                   + ": " +e.toString(), e);
           }
       }

       try {
           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());

           if (activity != null) {
               Context appContext =createBaseContextForActivity(r, activity);
               CharSequence title =r.activityInfo.loadLabel(appContext.getPackageManager());
               Configuration config = newConfiguration(mCompatConfiguration);
               if (r.overrideConfig != null){
                   config.updateFrom(r.overrideConfig);
               }
               if (DEBUG_CONFIGURATION)Slog.v(TAG, "Launching activity "
                       +r.activityInfo.name + " with config " + config);
               Window window = null;
               if (r.mPendingRemoveWindow!= null && r.mPreserveWindow) {
                   window =r.mPendingRemoveWindow;
                   r.mPendingRemoveWindow= null;
                  r.mPendingRemoveWindowManager = null;
               }
               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,window);

               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 {
                  mInstrumentation.callActivityOnCreate(activity, r.state);
               }
               if (!activity.mCalled) {
                   throw newSuperNotCalledException(
                       "Activity" + r.intent.getComponent().toShortString() +
                       " did notcall 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 newSuperNotCalledException(
                           "Activity" + r.intent.getComponent().toShortString() +
                           " did not call through tosuper.onPostCreate()");
                   }
               }
           }
           r.paused = true;

           mActivities.put(r.token, r);

       } catch (SuperNotCalledExceptione) {
           throw e;

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

       return activity;
   }

        可以看到在创建 Activity 实例的同时还创建了 ContextImpl 的实例

[Java] 纯文本查看 复制代码
if(activity != null) {
    // 创建一个 Activity
    ContextImpl appContext = newContextImpl();
    // 初始化该 ContextImpl 实例的相关属性
   appContext.init(r.packageInfo,r.token,this);
    // 将该 Activity 信息传递给该ContextImpl 实例   
    appContext.setOuterContext(activity);
}

Service 的创建

        通过startService或者bindService时,如果系统检测到需要新创建一个Service实例,就会回调handleCreateService()方法,完成相关数据操作。handleCreateService()函数位于 ActivityThread.java类,如下:

[Java] 纯文本查看 复制代码
//创建一个Service实例时同时创建ContextIml实例  
private final void handleCreateService(CreateServiceData data){  
    ... 
    //创建一个Service实例  
    Service service = null;  
    try { 
        java.lang.ClassLoader cl =packageInfo.getClassLoader();  
        service = (Service)cl.loadClass(data.info.name).newInstance(); 
    } catch (Exception e) {  
    } 
    ... 
    ContextImpl context = newContextImpl(); //创建一个ContextImpl对象实例  
    context.init(packageInfo, null, this);   //初始化该ContextIml实例的相关属性  
    //获得我们之前创建的Application对象信息  
    Application app =packageInfo.makeApplication(false, mInstrumentation);  
    //将该Service信息传递给该ContextImpl实例  
   context.setOuterContext(service); 
    ... 
}  

Context 的数量

        由上述创建 Context 的时机来分析,一个应用程序 App 共有的 Context 类型为三种,分别是:Application、Activity、Service。因此 Context 的数量的计算公式为:

Context 的数量 =  Activity 数量 + Service 数量 + 1

        1代表的是 Application ,因为一个 App 里可以有 N 个 Activity 和 Service,但是却只能有一个Application。
        当然,如果你细心的话,可能会疑问,所谓的四大组件,为什么在这里只有 Activity 和 Service 持有 Context,那BroadcastReceiver 以及 ContentProvider 呢?
        其实 BroadcastReceiver 和 ContentProvider 并不是 Context 的子类,他们所持有的 Context 是其他地方传过去的,并不能算是 Context。

        下篇 【进阶】从源码理清你对 Context 的疑问(下)

       点此进入:Android 人事+技术总贴
       点此进入:Android 基础篇总贴
       点此进入:Android 进阶篇总贴
       点此进入:Android 讨论区

       以上言论,如有错误或者表达不准确或者有纰漏的地方还请指正,同时欢迎大家在评论区留言给予一定的建议,我会根据大家的意见进行相应的改正,谢谢各位!


Context 源码的理解.html

357.58 KB, 阅读权限: 10, 下载次数: 4

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马