转载自:http://blog.csdn.net/myarrow/article/details/14121757
1. Context基本概念
1.1 Context是什么?
1) Context是一个抽象类,其通用实现在ContextImpl类中。
2) Context:是一个访问application环境全局信息的接口,通过它可以访问application的资源和相关的类,其主要功能如下:
• 启动Activity
• 启动和停止Service
• 发送广播消息(Intent)
• 注册广播消息(Intent)接收者
• 可以访问APK中各种资源(如Resources和AssetManager等)
• 可以访问Package的相关信息
• APK的各种权限管理
从以上分析可以看出,Context就是一个对APK包无所不知的大管家,大家需要什么,直接问它就可以了。
1.1.1 Context与View的关系
View与Context(或Activity)的关系类似于明星与经纪人的关系,所以创建View时,必须明确指定其Context(即经纪人或大管家),否则View就成不了明星。
1.2 Context家族关系
1.3 Context关键函数
- public abstract class Context {
-
-
- public abstract AssetManager getAssets();
-
-
- public abstract Resources getResources();
-
-
- public abstract PackageManager getPackageManager();
-
-
- public abstract ContentResolver getContentResolver();
-
-
- public abstract Looper getMainLooper();
-
-
- public abstract Context getApplicationContext();
-
-
- public final CharSequence getText(int resId) {
- return getResources().getText(resId);
- }
-
-
- public final String getString(int resId) {
- return getResources().getString(resId);
- }
-
- public final String getString(int resId, Object... formatArgs) {
- return getResources().getString(resId, formatArgs);
- }
-
-
- public abstract ClassLoader getClassLoader();
-
-
- public abstract String getPackageName();
-
-
- public abstract ApplicationInfo getApplicationInfo();
-
-
- public abstract SharedPreferences getSharedPreferences(String name,
- int mode);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public abstract File getExternalFilesDir(String type);
-
-
- public abstract File getObbDir();
-
-
- public abstract void startActivity(Intent intent);
-
-
- public void startActivityAsUser(Intent intent, UserHandle user) {
- throw new RuntimeException("Not implemented. Must override in a subclass.");
- }
-
-
-
-
- public abstract void startActivity(Intent intent, Bundle options);
-
-
- public abstract void startActivities(Intent[] intents);
-
-
- public abstract void startActivities(Intent[] intents, Bundle options);
-
-
- public abstract void sendBroadcast(Intent intent);
-
-
- public abstract void sendBroadcast(Intent intent,String receiverPermission);
-
- public abstract void sendOrderedBroadcast(Intent intent,String receiverPermission);
-
- public abstract void sendOrderedBroadcast(Intent intent,
- String receiverPermission, BroadcastReceiver resultReceiver,
- Handler scheduler, int initialCode, String initialData,
- Bundle initialExtras);
-
- public abstract void sendBroadcastAsUser(Intent intent, UserHandle user);
-
- public abstract void sendBroadcastAsUser(Intent intent, UserHandle user,
- String receiverPermission);
-
-
- public abstract Intent registerReceiver(BroadcastReceiver receiver,
- IntentFilter filter);
-
- public abstract Intent registerReceiver(BroadcastReceiver receiver,
- IntentFilter filter, String broadcastPermission, Handler scheduler);
-
- public abstract void unregisterReceiver(BroadcastReceiver receiver);
-
-
- public abstract ComponentName startService(Intent service);
-
-
- public abstract boolean stopService(Intent service);
-
-
- public abstract boolean bindService(Intent service, ServiceConnection conn,
- int flags);
-
-
-
- public abstract void unbindService(ServiceConnection conn);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public abstract Object getSystemService(String name);
-
- public abstract int checkPermission(String permission, int pid, int uid);
-
-
- public abstract Context createPackageContext(String packageName,
- int flags) throws PackageManager.NameNotFoundException;
-
-
- public abstract Context createDisplayContext(Display display);
- }
1.4 ContextImpl关键成员和函数
-
-
-
-
- class ContextImpl extends Context {
- private final static String TAG = "ContextImpl";
- private final static boolean DEBUG = false;
-
- private static final HashMap<String, SharedPreferencesImpl> sSharedPrefs =
- new HashMap<String, SharedPreferencesImpl>();
-
- LoadedApk mPackageInfo;
- private String mBasePackageName;
- private Resources mResources;
- ActivityThread mMainThread;
-
- @Override
- public AssetManager getAssets() {
- return getResources().getAssets();
- }
-
- @Override
- public Looper getMainLooper() {
- return mMainThread.getLooper();
- }
-
- @Override
- public Object getSystemService(String name) {
- ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
- return fetcher == null ? null : fetcher.getService(this);
- }
-
- @Override
- public void startActivity(Intent intent, Bundle options) {
- warnIfCallingFromSystemProcess();
- if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
- throw new AndroidRuntimeException(
- "Calling startActivity() from outside of an Activity "
- + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
- + " Is this really what you want?");
- }
- mMainThread.getInstrumentation().execStartActivity(
- getOuterContext(), mMainThread.getApplicationThread(), null,
- (Activity)null, intent, -1, options);
- }
- }
1.5 ContextWrapper
它只是对Context类的一种封装,它的构造函数包含了一个真正的Context引用,即ContextImpl对象。
-
-
-
-
-
- public class ContextWrapper extends Context {
- Context mBase;
-
- public ContextWrapper(Context base) {
- mBase = base;
- }
-
-
-
-
-
-
-
-
-
- protected void attachBaseContext(Context base) {
- if (mBase != null) {
- throw new IllegalStateException("Base context already set");
- }
- mBase = base;
- }
-
- @Override
- public Looper getMainLooper() {
- return mBase.getMainLooper();
- }
-
- @Override
- public Object getSystemService(String name) {
- return mBase.getSystemService(name);
- }
-
- @Override
- public void startActivity(Intent intent) {
- mBase.startActivity(intent);
- }
- }
1.6 ContextThemeWrapper
该类内部包含了主题(Theme)相关的接口,即android:theme属性指定的。只有Activity需要主题,Service不需要主题,所以Service直接继承于ContextWrapper类。
-
-
-
-
- public class ContextThemeWrapper extends ContextWrapper {
- private Context mBase;
- private int mThemeResource;
- private Resources.Theme mTheme;
- private LayoutInflater mInflater;
- private Configuration mOverrideConfiguration;
- private Resources mResources;
-
- public ContextThemeWrapper() {
- super(null);
- }
-
- public ContextThemeWrapper(Context base, int themeres) {
- super(base);
- mBase = base;
- mThemeResource = themeres;
- }
-
- @Override protected void attachBaseContext(Context newBase) {
- super.attachBaseContext(newBase);
- mBase = newBase;
- }
-
- @Override public void setTheme(int resid) {
- mThemeResource = resid;
- initializeTheme();
- }
-
- @Override public Resources.Theme getTheme() {
- if (mTheme != null) {
- return mTheme;
- }
-
- mThemeResource = Resources.selectDefaultTheme(mThemeResource,
- getApplicationInfo().targetSdkVersion);
- initializeTheme();
-
- return mTheme;
- }
- }
2. 何时创建Context
应用程序在以下几种情况下创建Context实例:
1) 创建Application 对象时, 而且整个App共一个Application对象
2) 创建Service对象时
3) 创建Activity对象时
因此应用程序App共有的Context数目公式为:
总Context实例个数 = Service个数 + Activity个数 + 1(Application对应的Context实例)
ActivityThread消息处理函数与本节相关的内容如下:
- public void handleMessage(Message msg) {
- if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
- switch (msg.what) {
- case LAUNCH_ACTIVITY: {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
- ActivityClientRecord r = (ActivityClientRecord)msg.obj;
-
- r.packageInfo = getPackageInfoNoCheck(
- r.activityInfo.applicationInfo, r.compatInfo);
- handleLaunchActivity(r, null);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- } break;
-
- case BIND_APPLICATION:
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
- AppBindData data = (AppBindData)msg.obj;
- handleBindApplication(data);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- break;
-
- case CREATE_SERVICE:
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
- handleCreateService((CreateServiceData)msg.obj);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- break;
-
- case BIND_SERVICE:
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
- handleBindService((BindServiceData)msg.obj);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- break;
- }
- }
2.1 创建Application对象时创建Context实例
每个应用程序在第一次启动时,都会首先创建一个Application对象。从startActivity流程可知,创建Application的时机在handleBindApplication()方法中,该函数位于 ActivityThread.java类中 ,相关代码如下:
-
- private void handleBindApplication(AppBindData data) {
- try {
-
-
- Application app = data.info.makeApplication(data.restrictedBackupMode, null);
- mInitialApplication = app;
- ...
- } finally {
- StrictMode.setThreadPolicy(savedPolicy);
- }
- }
-
-
- public Application makeApplication(boolean forceDefaultAppClass,
- Instrumentation instrumentation) {
- if (mApplication != null) {
- return mApplication;
- }
-
- Application app = null;
-
- String appClass = mApplicationInfo.className;
- if (forceDefaultAppClass || (appClass == null)) {
- appClass = "android.app.Application";
- }
-
- try {
- java.lang.ClassLoader cl = getClassLoader();
- ContextImpl appContext = new ContextImpl();
- appContext.init(this, null, mActivityThread);
- app = mActivityThread.mInstrumentation.newApplication(
- cl, appClass, appContext);
- appContext.setOuterContext(app);
- } catch (Exception e) {
- ...
- }
- mActivityThread.mAllApplications.add(app);
- mApplication = app;
-
- return app;
- }
2.2 创建Activity对象时创建Context实例
通过startActivity()或startActivityForResult()请求启动一个Activity时,如果系统检测需要新建一个Activity对象时,就会回调handleLaunchActivity()方法,该方法继而调用performLaunchActivity()方法,去创建一个Activity实例,并且回调onCreate(),onStart()方法等,函数都位于 ActivityThread.java类 ,相关代码如下:
- private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
- ...
- Activity a = performLaunchActivity(r, customIntent);
-
- if (a != null) {
- r.createdConfig = new Configuration(mConfiguration);
- Bundle oldState = r.state;
- handleResumeActivity(r.token, false, r.isForward,
- !r.activity.mFinished && !r.startsNotResumed);
- ...
- }
- ...
- }
-
- private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
- ...
- 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);
- if (r.state != null) {
- r.state.setClassLoader(cl);
- }
- } catch (Exception e) {
- ...
- }
-
- try {
- Application app = r.packageInfo.makeApplication(false, mInstrumentation);
-
- if (activity != null) {
- Context appContext = createBaseContextForActivity(r, activity);
- CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
- Configuration config = new Configuration(mCompatConfiguration);
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
- + r.activityInfo.name + " with config " + config);
- activity.attach(appContext, this, getInstrumentation(), r.token,
- r.ident, app, r.intent, r.activityInfo, title, r.parent,
- r.embeddedID, r.lastNonConfigurationInstances, config);
-
- if (customIntent != null) {
- activity.mIntent = customIntent;
- }
- r.lastNonConfigurationInstances = null;
- activity.mStartedActivity = false;
- int theme = r.activityInfo.getThemeResource();
- if (theme != 0) {
- activity.setTheme(theme);
- }
-
-
- mActivities.put(r.token, r);
-
- } catch (SuperNotCalledException e) {
- ...
-
- } catch (Exception e) {
- ...
- }
-
- return activity;
- }
- private Context createBaseContextForActivity(ActivityClientRecord r,
- final Activity activity) {
- ContextImpl appContext = new ContextImpl();
- appContext.init(r.packageInfo, r.token, this);
- appContext.setOuterContext(activity);
-
-
-
-
- Context baseContext = appContext;
- String pkgName = SystemProperties.get("debug.second-display.pkg");
- if (pkgName != null && !pkgName.isEmpty()
- && r.packageInfo.mPackageName.contains(pkgName)) {
- DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
- for (int displayId : dm.getDisplayIds()) {
- if (displayId != Display.DEFAULT_DISPLAY) {
- Display display = dm.getRealDisplay(displayId);
- baseContext = appContext.createDisplayContext(display);
- break;
- }
- }
- }
- return baseContext;
- }
2.3 创建Service对象时创建Context实例
通过startService或者bindService时,如果系统检测到需要新创建一个Service实例,就会回调handleCreateService()方法,完成相关数据操作。handleCreateService()函数位于 ActivityThread.java类,如下:
- private void handleCreateService(CreateServiceData data) {
-
-
- unscheduleGcIdler();
-
- LoadedApk packageInfo = getPackageInfoNoCheck(
- data.info.applicationInfo, data.compatInfo);
- Service service = null;
- try {
- java.lang.ClassLoader cl = packageInfo.getClassLoader();
- service = (Service) cl.loadClass(data.info.name).newInstance();
- } catch (Exception e) {
- if (!mInstrumentation.onException(service, e)) {
- throw new RuntimeException(
- "Unable to instantiate service " + data.info.name
- + ": " + e.toString(), e);
- }
- }
-
- try {
- if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
-
- ContextImpl context = new ContextImpl();
- context.init(packageInfo, null, this);
-
- Application app = packageInfo.makeApplication(false, mInstrumentation);
- context.setOuterContext(service);
- service.attach(context, this, data.info.name, data.token, app,
- ActivityManagerNative.getDefault());
- service.onCreate();
- mServices.put(data.token, service);
- try {
- ActivityManagerNative.getDefault().serviceDoneExecuting(
- data.token, 0, 0, 0);
- } catch (RemoteException e) {
-
- }
- } catch (Exception e) {
- if (!mInstrumentation.onException(service, e)) {
- throw new RuntimeException(
- "Unable to create service " + data.info.name
- + ": " + e.toString(), e);
- }
- }
- }
3. 小结
通过对ContextImp的分析可知,其方法的大多数操作都是直接调用其属性mPackageInfo(该属性类型为PackageInfo)的相关方法而来。这说明ContextImp是一种轻量级类,而PackageInfo才是真正重量级的类。而一个App里的所有ContextImpl实例,都对应同一个packageInfo对象。
注:参考http://blog.csdn.net/qinjuning/article/details/7310620