Android中Context的继承关系详解

tech2022-08-29  99

原文地址:https://www.jianshu.com/p/b68276bb2f33

 

简介

Context在Android中表明上下文环境,可以用来启动Activity,开启服务,获取应用信息等作用。

继承关系

Android中的Context.png

Context

Context是一个抽象类,内部定义很多抽象类,包括startActivity,startService ,getResource 等方法

ContextImpl

ContextImpl继承Context,是Context的具体实现类

ContextWrapper

ContextWrapper是Context的包装类,是对外提供的接口类,继承Context,实现抽象方法,实现的方法交由ContextImpl来实现。其中attachBaseContext()是建立与ContextImpl的联系的桥梁。

ContextImpl和ContextWrapper的关系

两者的关系 ,可以看作成是代理模式,ContextImpl代理ContextWrapper,Context是代理接口!

ContextThemeWrapper Service Application

三者都是继承ContextWrapper其中ContextThemeWrapper是带有主题的Context

Activity

Activity是继承ContextThemeWrapper

ContextWrapper中的源码以及mBase

 

public AssetManager getAssets() { return mBase.getAssets(); } @Override public Resources getResources() { return mBase.getResources(); } @Override public PackageManager getPackageManager() { return mBase.getPackageManager(); } @Override public ContentResolver getContentResolver() { return mBase.getContentResolver(); } @Override public Looper getMainLooper() { return mBase.getMainLooper(); } @Override public Executor getMainExecutor() { return mBase.getMainExecutor(); } @Override public Context getApplicationContext() { return mBase.getApplicationContext(); } @Override public void setTheme(int resid) { mBase.setTheme(resid); } /** @hide */ @Override @UnsupportedAppUsage public int getThemeResId() { return mBase.getThemeResId(); } @Override public Resources.Theme getTheme() { return mBase.getTheme(); } @Override public ClassLoader getClassLoader() { return mBase.getClassLoader(); } @Override public String getPackageName() { return mBase.getPackageName(); } /** @hide */ @Override @UnsupportedAppUsage public String getBasePackageName() { return mBase.getBasePackageName(); } @Override public ApplicationInfo getApplicationInfo() { return mBase.getApplicationInfo(); } @Override public String getPackageResourcePath() { return mBase.getPackageResourcePath(); } @Override public String getPackageCodePath() { return mBase.getPackageCodePath(); } @Override public SharedPreferences getSharedPreferences(String name, int mode) { return mBase.getSharedPreferences(name, mode); } /** @removed */ @Override public SharedPreferences getSharedPreferences(File file, int mode) { return mBase.getSharedPreferences(file, mode); } /** @removed */ @Override public File getSharedPreferencesPath(String name) { return mBase.getSharedPreferencesPath(name); } @Override public void startActivity(Intent intent) { mBase.startActivity(intent); } /** @hide */ @Override public void startActivityAsUser(Intent intent, UserHandle user) { mBase.startActivityAsUser(intent, user); } /** @hide **/ public void startActivityForResult( String who, Intent intent, int requestCode, Bundle options) { mBase.startActivityForResult(who, intent, requestCode, options); } 在ContextWrapper中可以看见我们熟悉的方法 startActivity,gegetSharedPreferencest,getPackageInfo,getSystemInfo等一系列方法在这些方法都交由mBase来处理了

mBase

 

public ContextWrapper(Context base) { mBase = base; } protected void attachBaseContext(Context base) { if (mBase != null) { throw new IllegalStateException("Base context already set"); } mBase = base; } mBase的赋值可以有构造方法和attachBaseContext()方法来进行这里的mBase实则是ContextImpl,在调用atatchBaseContext()方法的时候,实则传递的是ContextImpl的实例。

几个问题

一个应用中Context的数量?

Activity数量+Service数量+Application数量(通常为1,一个进程中只有一个Application)

getApplication()和getApplicationContext()的关系

两者获取的都是应用程序的Application对象,获取到的是同一个对象 getApplication() 通常用于Service,Activity 中,而getApplicationContext()用于比如BroadcastReceiver中获取Application getApplicationContext同时也是ContextWrapper中的,相比较于getApplication(),getApplicationContext的作用域更广一些,getApplication()从语意上看,更强一些就是用于获取Application

自定义的Application 对外提供实例不需要做多重检查了?

Application本身是单利,全局就仅仅有一个,不需要进行多重检查了,哈哈哈!

能在自定义Application的构造方法中 调用实现Context中的抽象方法吗?

不可以的,会报错; 因为 Application是继承ContextWrapper的,而ContextWrapper中实现的抽象方法是交由ContextImpl来实现的,ContextImpl的获取是交由内部的attachBaseContext的,如果在构造方法中调用实现的抽象方法,会报错的,此时mBase为null

不能在构造方法中调用实现的抽象方法,可以在 attachBaseContext(){super() 之后调用},也可以在onCreate中调用

 

最新回复(0)