android context.java_Android开发中Context类的作用以及Context的详细用法

e69930c277362f9d60d61f4b0ad7510c.png

Context基本概念

Context是什么?

1) Context是一个抽象类,其通用实现在ContextImpl类中。

2) Context:是一个访问application环境全局信息的接口,通过它可以访问application的资源和相关的类,其主要功能如下:

启动Activity

启动和停止Service

发送广播消息(Intent)

注册广播消息(Intent)接收者

可以访问APK中各种资源(如Resources和AssetManager等)

可以访问Package的相关信息

APK的各种权限管理

从以上分析可以看出,Context就是一个对APK包无所不知的大管家,大家需要什么,直接问它就可以了。

Context与View的关系

View与Context(或Activity)的关系类似于明星与经纪人的关系,所以创建View时,必须明确指定其Context(即经纪人或大管家),否则View就成不了明星。

Context家族关系

b658ab1bf50f8606666f8e5fb6ffbd3f.png

Context关键函数

1 public abstract classContext {2

3 //获取应用程序包的AssetManager实例

4 public abstractAssetManager getAssets();5

6 //获取应用程序包的Resources实例

7 public abstractResources getResources();8

9 //获取PackageManager实例,以查看全局package信息

10 public abstractPackageManager getPackageManager();11

12 //获取应用程序包的ContentResolver实例

13 public abstractContentResolver getContentResolver();14

15 //它返回当前进程的主线程的Looper,此线程分发调用给应用组件(activities, services等)

16 public abstractLooper getMainLooper();17

18 //返回当前进程的单实例全局Application对象的Context

19 public abstractContext getApplicationContext();20

21 //从string表中获取本地化的、格式化的字符序列

22 public final CharSequence getText(intresId) {23 returngetResources().getText(resId);24 }25

26 //从string表中获取本地化的字符串

27 public final String getString(intresId) {28 returngetResources().getString(resId);29 }30

31 public final String getString(intresId, Object... formatArgs) {32 returngetResources().getString(resId, formatArgs);33 }34

35 //返回一个可用于获取包中类信息的class loader

36 public abstractClassLoader getClassLoader();37

38 //返回应用程序包名

39 public abstractString getPackageName();40

41 //返回应用程序信息

42 public abstractApplicationInfo getApplicationInfo();43

44 //根据文件名获取SharedPreferences

45 public abstractSharedPreferences getSharedPreferences(String name,46 intmode);47

48 //其根目录为: Environment.getExternalStorageDirectory()

49 /*

50 * @param type The type of files directory to return. May be null for51 * the root of the files directory or one of52 * the following Environment constants for a subdirectory:53 * {@link android.os.Environment#DIRECTORY_MUSIC},54 * {@link android.os.Environment#DIRECTORY_PODCASTS},55 * {@link android.os.Environment#DIRECTORY_RINGTONES},56 * {@link android.os.Environment#DIRECTORY_ALARMS},57 * {@link android.os.Environment#DIRECTORY_NOTIFICATIONS},58 * {@link android.os.Environment#DIRECTORY_PICTURES}, or59 * {@link android.os.Environment#DIRECTORY_MOVIES}.60 */

61 public abstractFile getExternalFilesDir(String type);62

63 //返回应用程序obb文件路径

64 public abstractFile getObbDir();65

66 //启动一个新的activity

67 public abstract voidstartActivity(Intent intent);68

69 //启动一个新的activity

70 public voidstartActivityAsUser(Intent intent, UserHandle user) {71 throw new RuntimeException("Not implemented. Must override in a subclass.");72 }73

74 //启动一个新的activity75 //intent: 将被启动的activity的描述信息76 //options: 描述activity将如何被启动

77 public abstract voidstartActivity(Intent intent, Bundle options);78

79 //启动多个新的activity

80 public abstract voidstartActivities(Intent[] intents);81

82 //启动多个新的activity

83 public abstract voidstartActivities(Intent[] intents, Bundle options);84

85 //广播一个intent给所有感兴趣的接收者,异步机制

86 public abstract voidsendBroadcast(Intent intent);87

88 //广播一个intent给所有感兴趣的接收者,异步机制

89 public abstract voidsendBroadcast(Intent intent,String receiverPermission);90

91 public abstract voidsendOrderedBroadcast(Intent intent,String receiverPermission);92

93 public abstract voidsendOrderedBroadcast(Intent intent,94 String receiverPermission, BroadcastReceiver resultReceiver,95 Handler scheduler, intinitialCode, String initialData,96 Bundle initialExtras);97

98 public abstract voidsendBroadcastAsUser(Intent intent, UserHandle user);99

100 public abstract voidsendBroadcastAsUser(Intent intent, UserHandle user,101 String receiverPermission);102

103 //注册一个BroadcastReceiver,且它将在主activity线程中运行

104 public abstractIntent registerReceiver(BroadcastReceiver receiver,105 IntentFilter filter);106

107 public abstractIntent registerReceiver(BroadcastReceiver receiver,108 IntentFilter filter, String broadcastPermission, Handler scheduler);109

110 public abstract voidunregisterReceiver(BroadcastReceiver receiver);111

112 //请求启动一个application service

113 public abstractComponentName startService(Intent service);114

115 //请求停止一个application service

116 public abstract booleanstopService(Intent service);117

118 //连接一个应用服务,它定义了application和service间的依赖关系

119 public abstract booleanbindService(Intent service, ServiceConnection conn,120 intflags);121

122 //断开一个应用服务,当服务重新开始时,将不再接收到调用,123 //且服务允许随时停止

124 public abstract voidunbindService(ServiceConnection conn);125

126 //返回系统级service句柄

127 /*

128 * @see #WINDOW_SERVICE129 * @see android.view.WindowManager130 * @see #LAYOUT_INFLATER_SERVICE131 * @see android.view.LayoutInflater132 * @see #ACTIVITY_SERVICE133 * @see android.app.ActivityManager134 * @see #POWER_SERVICE135 * @see android.os.PowerManager136 * @see #ALARM_SERVICE137 * @see android.app.AlarmManager138 * @see #NOTIFICATION_SERVICE139 * @see android.app.NotificationManager140 * @see #KEYGUARD_SERVICE141 * @see android.app.KeyguardManager142 * @see #LOCATION_SERVICE143 * @see android.location.LocationManager144 * @see #SEARCH_SERVICE145 * @see android.app.SearchManager146 * @see #SENSOR_SERVICE147 * @see android.hardware.SensorManager148 * @see #STORAGE_SERVICE149 * @see android.os.storage.StorageManager150 * @see #VIBRATOR_SERVICE151 * @see android.os.Vibrator152 * @see #CONNECTIVITY_SERVICE153 * @see android.net.ConnectivityManager154 * @see #WIFI_SERVICE155 * @see android.net.wifi.WifiManager156 * @see #AUDIO_SERVICE157 * @see android.media.AudioManager158 * @see #MEDIA_ROUTER_SERVICE159 * @see android.media.MediaRouter160 * @see #TELEPHONY_SERVICE161 * @see android.telephony.TelephonyManager162 * @see #INPUT_METHOD_SERVICE163 * @see android.view.inputmethod.InputMethodManager164 * @see #UI_MODE_SERVICE165 * @see android.app.UiModeManager166 * @see #DOWNLOAD_SERVICE167 * @see android.app.DownloadManager168 */

169 public abstractObject getSystemService(String name);170

171 public abstract int checkPermission(String permission, int pid, intuid);172

173 //返回一个新的与application name对应的Context对象

174 public abstractContext createPackageContext(String packageName,175 int flags) throwsPackageManager.NameNotFoundException;176

177 //返回基于当前Context对象的新对象,其资源与display相匹配

178 public abstractContext createDisplayContext(Display display);179 }

ContextImpl关键成员和函数

1 /**

2 * Common implementation of Context API, which provides the base3 * context object for Activity and other application components.4 */

5 class ContextImpl extendsContext {6 private final static String TAG = "ContextImpl";7 private final static boolean DEBUG = false;8

9 private static final HashMap sSharedPrefs =

10 new HashMap();11

12 /*package*/ LoadedApk mPackageInfo; //关键数据成员

13 privateString mBasePackageName;14 privateResources mResources;15 /*package*/ ActivityThread mMainThread; //主线程

16

17 @Override18 publicAssetManager getAssets() {19 returngetResources().getAssets();20 }21

22 @Override23 publicLooper getMainLooper() {24 returnmMainThread.getLooper();25 }26

27 @Override28 publicObject getSystemService(String name) {29 ServiceFetcher fetcher =SYSTEM_SERVICE_MAP.get(name);30 return fetcher == null ? null : fetcher.getService(this);31 }32

33 @Override34 public voidstartActivity(Intent intent, Bundle options) {35 warnIfCallingFromSystemProcess();36 if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {37 throw newAndroidRuntimeException(38 "Calling startActivity() from outside of an Activity "

39 + " context requires the FLAG_ACTIVITY_NEW_TASK flag."

40 + " Is this really what you want?");41 }42 mMainThread.getInstrumentation().execStartActivity(43 getOuterContext(), mMainThread.getApplicationThread(), null,44 (Activity)null, intent, -1, options);45 }46 }

ContextWrapper

它只是对Context类的一种封装,它的构造函数包含了一个真正的Context引用,即ContextImpl对象。

1 /**

2 * Proxying implementation of Context that simply delegates all of its calls to3 * another Context. Can be subclassed to modify behavior without changing4 * the original Context.5 */

6 public class ContextWrapper extendsContext {7 Context mBase; //该属性指向一个ContextIml实例

8

9 publicContextWrapper(Context base) {10 mBase =base;11 }12

13 /**

14 * Set the base context for this ContextWrapper. All calls will then be15 * delegated to the base context. Throws16 * IllegalStateException if a base context has already been set.17 *18 *@parambase The new base context for this wrapper.19 * 创建Application、Service、Activity,会调用该方法给mBase属性赋值20 */

21 protected voidattachBaseContext(Context base) {22 if (mBase != null) {23 throw new IllegalStateException("Base context already set");24 }25 mBase =base;26 }27

28 @Override29 publicLooper getMainLooper() {30 returnmBase.getMainLooper();31 }32

33 @Override34 publicObject getSystemService(String name) {35 returnmBase.getSystemService(name);36 }37

38 @Override39 public voidstartActivity(Intent intent) {40 mBase.startActivity(intent);41 }42 }

ContextThemeWrapper

该类内部包含了主题(Theme)相关的接口,即android:theme属性指定的。只有Activity需要主题,Service不需要主题,所以Service直接继承于ContextWrapper类。

1 /**

2 * A ContextWrapper that allows you to modify the theme from what is in the3 * wrapped context.4 */

5 public class ContextThemeWrapper extendsContextWrapper {6 privateContext mBase;7 private intmThemeResource;8 privateResources.Theme mTheme;9 privateLayoutInflater mInflater;10 privateConfiguration mOverrideConfiguration;11 privateResources mResources;12

13 publicContextThemeWrapper() {14 super(null);15 }16

17 public ContextThemeWrapper(Context base, intthemeres) {18 super(base);19 mBase =base;20 mThemeResource =themeres;21 }22

23 @Override protected voidattachBaseContext(Context newBase) {24 super.attachBaseContext(newBase);25 mBase =newBase;26 }27

28 @Override public void setTheme(intresid) {29 mThemeResource =resid;30 initializeTheme();31 }32

33 @Override publicResources.Theme getTheme() {34 if (mTheme != null) {35 returnmTheme;36 }37

38 mThemeResource =Resources.selectDefaultTheme(mThemeResource,39 getApplicationInfo().targetSdkVersion);40 initializeTheme();41

42 returnmTheme;43 }44 }

何时创建Context

应用程序在以下几种情况下创建Context实例:

1) 创建Application 对象时, 而且整个App共一个Application对象

2) 创建Service对象时

3) 创建Activity对象时

因此应用程序App共有的Context数目公式为:

总Context实例个数 = Service个数 + Activity个数 + 1(Application对应的Context实例)

ActivityThread消息处理函数与本节相关的内容如下:

1 public voidhandleMessage(Message msg) {2 if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " +codeToString(msg.what));3 switch(msg.what) {4 case LAUNCH_ACTIVITY: { //创建Activity对象

5 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");6 ActivityClientRecord r =(ActivityClientRecord)msg.obj;7

8 r.packageInfo =getPackageInfoNoCheck(9 r.activityInfo.applicationInfo, r.compatInfo);10 handleLaunchActivity(r, null);11 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);12 } break;13

14 case BIND_APPLICATION: //创建Application对象

15 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");16 AppBindData data =(AppBindData)msg.obj;17 handleBindApplication(data);18 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);19 break;20

21 case CREATE_SERVICE: //创建Service对象

22 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");23 handleCreateService((CreateServiceData)msg.obj);24 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);25 break;26

27 case BIND_SERVICE: //Bind Service对象

28 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");29 handleBindService((BindServiceData)msg.obj);30 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);31 break;32 }33 }

创建Application对象时创建Context实例

每个应用程序在第一次启动时,都会首先创建一个Application对象。从startActivity流程可知,创建Application的时机在handleBindApplication()方法中,该函数位于 ActivityThread.java类中 ,相关代码如下:

1 //ActivityThread.java

2 private voidhandleBindApplication(AppBindData data) {3 try{4 //If the app is being launched for full backup or restore, bring it up in5 //a restricted environment with the base application class.

6 Application app = data.info.makeApplication(data.restrictedBackupMode, null);7 mInitialApplication =app;8 ...9 } finally{10 StrictMode.setThreadPolicy(savedPolicy);11 }12 }13

14 //LoadedApk.java

15 public Application makeApplication(booleanforceDefaultAppClass,16 Instrumentation instrumentation) {17 if (mApplication != null) {18 returnmApplication;19 }20

21 Application app = null;22

23 String appClass =mApplicationInfo.className;24 if (forceDefaultAppClass || (appClass == null)) {25 appClass = "android.app.Application";26 }27

28 try{29 java.lang.ClassLoader cl =getClassLoader();30 ContextImpl appContext = new ContextImpl(); //创建ContextImpl实例

31 appContext.init(this, null, mActivityThread);32 app =mActivityThread.mInstrumentation.newApplication(33 cl, appClass, appContext);34 appContext.setOuterContext(app); //将Application实例传递给Context实例

35 } catch(Exception e) {36 ...37 }38 mActivityThread.mAllApplications.add(app);39 mApplication =app;40

41 returnapp;42 }43 privateContext createBaseContextForActivity(ActivityClientRecord r,44 finalActivity activity) {45 ContextImpl appContext = new ContextImpl(); //创建ContextImpl实例

46 appContext.init(r.packageInfo, r.token, this);47 appContext.setOuterContext(activity);48

49 //For debugging purposes, if the activity's package name contains the value of50 //the "debug.use-second-display" system property as a substring, then show51 //its content on a secondary display if there is one.

52 Context baseContext =appContext;53 String pkgName = SystemProperties.get("debug.second-display.pkg");54 if (pkgName != null && !pkgName.isEmpty()55 &&r.packageInfo.mPackageName.contains(pkgName)) {56 DisplayManagerGlobal dm =DisplayManagerGlobal.getInstance();57 for (intdisplayId : dm.getDisplayIds()) {58 if (displayId !=Display.DEFAULT_DISPLAY) {59 Display display =dm.getRealDisplay(displayId);60 baseContext =appContext.createDisplayContext(display);61 break;62 }63 }64 }65 returnbaseContext;66 }

创建Service对象时创建Context实例

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

1 private voidhandleCreateService(CreateServiceData data) {2 //If we are getting ready to gc after going to the background, well3 //we are back active so skip it.

4 unscheduleGcIdler();5

6 LoadedApk packageInfo =getPackageInfoNoCheck(7 data.info.applicationInfo, data.compatInfo);8 Service service = null;9 try{10 java.lang.ClassLoader cl =packageInfo.getClassLoader();11 service =(Service) cl.loadClass(data.info.name).newInstance();12 } catch(Exception e) {13 if (!mInstrumentation.onException(service, e)) {14 throw newRuntimeException(15 "Unable to instantiate service " +data.info.name16 + ": " +e.toString(), e);17 }18 }19

20 try{21 if (localLOGV) Slog.v(TAG, "Creating service " +data.info.name);22

23 ContextImpl context = new ContextImpl(); //创建ContextImpl实例

24 context.init(packageInfo, null, this);25

26 Application app = packageInfo.makeApplication(false, mInstrumentation);27 context.setOuterContext(service);28 service.attach(context, this, data.info.name, data.token, app,29 ActivityManagerNative.getDefault());30 service.onCreate();31 mServices.put(data.token, service);32 try{33 ActivityManagerNative.getDefault().serviceDoneExecuting(34 data.token, 0, 0, 0);35 } catch(RemoteException e) {36 //nothing to do.

37 }38 } catch(Exception e) {39 if (!mInstrumentation.onException(service, e)) {40 throw newRuntimeException(41 "Unable to create service " +data.info.name42 + ": " +e.toString(), e);43 }44 }45 }

1 private voidhandleCreateService(CreateServiceData data) {2 //If we are getting ready to gc after going to the background, well3 //we are back active so skip it.

4 unscheduleGcIdler();5

6 LoadedApk packageInfo =getPackageInfoNoCheck(7 data.info.applicationInfo, data.compatInfo);8 Service service = null;9 try{10 java.lang.ClassLoader cl =packageInfo.getClassLoader();11 service =(Service) cl.loadClass(data.info.name).newInstance();12 } catch(Exception e) {13 if (!mInstrumentation.onException(service, e)) {14 throw newRuntimeException(15 "Unable to instantiate service " +data.info.name16 + ": " +e.toString(), e);17 }18 }19

20 try{21 if (localLOGV) Slog.v(TAG, "Creating service " +data.info.name);22

23 ContextImpl context = new ContextImpl(); //创建ContextImpl实例

24 context.init(packageInfo, null, this);25

26 Application app = packageInfo.makeApplication(false, mInstrumentation);27 context.setOuterContext(service);28 service.attach(context, this, data.info.name, data.token, app,29 ActivityManagerNative.getDefault());30 service.onCreate();31 mServices.put(data.token, service);32 try{33 ActivityManagerNative.getDefault().serviceDoneExecuting(34 data.token, 0, 0, 0);35 } catch(RemoteException e) {36 //nothing to do.

37 }38 } catch(Exception e) {39 if (!mInstrumentation.onException(service, e)) {40 throw newRuntimeException(41 "Unable to create service " +data.info.name42 + ": " +e.toString(), e);43 }44 }45 }

小结

通过对ContextImp的分析可知,其方法的大多数操作都是直接调用其属性mPackageInfo(该属性类型为PackageInfo)的相关方法而来。这说明ContextImp是一种轻量级类,而PackageInfo才是真正重量级的类。而一个App里的所有ContextImpl实例,都对应同一个packageInfo对象。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值