1、Context類的使用場景java
①、建立Application對象時,並且整個app公用一個Application對象android
②、建立Service對象時app
③、建立Activity對象時異步
2、應用程序共有幾個Context的公式ide
①、 Context(總)=Context(service個數)+Context(activity個數)+1(一個application對象)函數
3、Context概念oop
①、Context是一個抽象類,其通用實如今ContextImpl類中。fetch
②、Context是維持Android程序中各組件能過正常工做的一個核心功能類,開發中稱:上下文ui
③、Context:是一個訪問application(應用程序)環境全局信息的接口,經過它能夠訪問application的資源和相關的類,其主要功能以下:this
1)、啓動Activity
2)、啓動和中止Service
3)、發送廣播消息(Intent)
4)、註冊廣播消息(Intent)接收者
5)、能夠訪問APK中各類資源(如Resources和AssetManager等)
6)、能夠訪問Package的相關信息
7)、APK的各類權限管理
4、Context的繼承
①、ContextIML(mPackageInfo)和ContextWrapper(mBase : Context)都繼承自Context
②、Context API的通用實現,他爲Activity和其餘application組件提供基本的context對象
③、Context代理實現,他簡單地把調用請求發送給另外一個context
④、service、contextThemeWrapper、application皆繼承自contextWrapper,activity繼承自contextThemeWrapper
5、關鍵函數
public abstract class Context { // 獲取應用程序包的AssetManager實例 public abstract AssetManager getAssets(); // 獲取應用程序包的Resources實例 public abstract Resources getResources(); // 獲取PackageManager實例,以查看全局package信息 public abstract PackageManager getPackageManager(); // 獲取應用程序包的ContentResolver實例 public abstract ContentResolver getContentResolver(); // 它返回當前進程的主線程的Looper,此線程分發調用給應用組件(activities, services等) public abstract Looper getMainLooper(); // 返回當前進程的單實例全局Application對象的Context public abstract Context getApplicationContext(); // 從string表中獲取本地化的、格式化的字符序列 public final CharSequence getText(int resId) { return getResources().getText(resId); } // 從string表中獲取本地化的字符串 public final String getString(int resId) { return getResources().getString(resId); } public final String getString(int resId, Object... formatArgs) { return getResources().getString(resId, formatArgs); } // 返回一個可用於獲取包中類信息的class loader public abstract ClassLoader getClassLoader(); // 返回應用程序包名 public abstract String getPackageName(); // 返回應用程序信息 public abstract ApplicationInfo getApplicationInfo(); // 根據文件名獲取SharedPreferences public abstract SharedPreferences getSharedPreferences(String name, int mode); // 其根目錄爲: Environment.getExternalStorageDirectory() /* * @param type The type of files directory to return. May be null for * the root of the files directory or one of * the following Environment constants for a subdirectory: * {@link android.os.Environment#DIRECTORY_MUSIC}, * {@link android.os.Environment#DIRECTORY_PODCASTS}, * {@link android.os.Environment#DIRECTORY_RINGTONES}, * {@link android.os.Environment#DIRECTORY_ALARMS}, * {@link android.os.Environment#DIRECTORY_NOTIFICATIONS}, * {@link android.os.Environment#DIRECTORY_PICTURES}, or * {@link android.os.Environment#DIRECTORY_MOVIES}. */ public abstract File getExternalFilesDir(String type); // 返回應用程序obb文件路徑 public abstract File getObbDir(); // 啓動一個新的activity public abstract void startActivity(Intent intent); // 啓動一個新的activity public void startActivityAsUser(Intent intent, UserHandle user) { throw new RuntimeException("Not implemented. Must override in a subclass."); } // 啓動一個新的activity // intent: 將被啓動的activity的描述信息 // options: 描述activity將如何被啓動 public abstract void startActivity(Intent intent, Bundle options); // 啓動多個新的activity public abstract void startActivities(Intent[] intents); // 啓動多個新的activity public abstract void startActivities(Intent[] intents, Bundle options); // 廣播一個intent給全部感興趣的接收者,異步機制 public abstract void sendBroadcast(Intent 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); // 註冊一個BroadcastReceiver,且它將在主activity線程中運行 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); // 請求啓動一個application service public abstract ComponentName startService(Intent service); // 請求中止一個application service public abstract boolean stopService(Intent service); // 鏈接一個應用服務,它定義了application和service間的依賴關係 public abstract boolean bindService(Intent service, ServiceConnection conn, int flags); // 斷開一個應用服務,當服務從新開始時,將再也不接收到調用, // 且服務容許隨時中止 public abstract void unbindService(ServiceConnection conn); // 返回系統級service句柄 /* * @see #WINDOW_SERVICE * @see android.view.WindowManager * @see #LAYOUT_INFLATER_SERVICE * @see android.view.LayoutInflater * @see #ACTIVITY_SERVICE * @see android.app.ActivityManager * @see #POWER_SERVICE * @see android.os.PowerManager * @see #ALARM_SERVICE * @see android.app.AlarmManager * @see #NOTIFICATION_SERVICE * @see android.app.NotificationManager * @see #KEYGUARD_SERVICE * @see android.app.KeyguardManager * @see #LOCATION_SERVICE * @see android.location.LocationManager * @see #SEARCH_SERVICE * @see android.app.SearchManager * @see #SENSOR_SERVICE * @see android.hardware.SensorManager * @see #STORAGE_SERVICE * @see android.os.storage.StorageManager * @see #VIBRATOR_SERVICE * @see android.os.Vibrator * @see #CONNECTIVITY_SERVICE * @see android.net.ConnectivityManager * @see #WIFI_SERVICE * @see android.net.wifi.WifiManager * @see #AUDIO_SERVICE * @see android.media.AudioManager * @see #MEDIA_ROUTER_SERVICE * @see android.media.MediaRouter * @see #TELEPHONY_SERVICE * @see android.telephony.TelephonyManager * @see #INPUT_METHOD_SERVICE * @see android.view.inputmethod.InputMethodManager * @see #UI_MODE_SERVICE * @see android.app.UiModeManager * @see #DOWNLOAD_SERVICE * @see android.app.DownloadManager */ public abstract Object getSystemService(String name); public abstract int checkPermission(String permission, int pid, int uid); // 返回一個新的與application name對應的Context對象 public abstract Context createPackageContext(String packageName, int flags) throws PackageManager.NameNotFoundException; // 返回基於當前Context對象的新對象,其資源與display相匹配 public abstract Context createDisplayContext(Display display); }
6、ContextIML關鍵成員以及函數
1 /** 2 * Common implementation of Context API, which provides the base 3 * context object for Activity and other application components. 4 */ 5 class ContextImpl extends Context { 6 private final static String TAG = "ContextImpl"; 7 private final static boolean DEBUG = false; 8 9 private static final HashMap<String, SharedPreferencesImpl> sSharedPrefs = 10 new HashMap<String, SharedPreferencesImpl>(); 11 12 /*package*/ LoadedApk mPackageInfo; // 關鍵數據成員 13 private String mBasePackageName; 14 private Resources mResources; 15 /*package*/ ActivityThread mMainThread; // 主線程 16 17 @Override 18 public AssetManager getAssets() { 19 return getResources().getAssets(); 20 } 21 22 @Override 23 public Looper getMainLooper() { 24 return mMainThread.getLooper(); 25 } 26 27 @Override 28 public Object getSystemService(String name) { 29 ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name); 30 return fetcher == null ? null : fetcher.getService(this); 31 } 32 33 @Override 34 public void startActivity(Intent intent, Bundle options) { 35 warnIfCallingFromSystemProcess(); 36 if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { 37 throw new AndroidRuntimeException( 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 }
7、ContextWrapper
它只是對Context類的一種封裝,它的構造函數包含了一個真正的Context引用,即ContextImpl對象
1 /** 2 * Proxying implementation of Context that simply delegates all of its calls to 3 * another Context. Can be subclassed to modify behavior without changing 4 * the original Context. 5 */ 6 public class ContextWrapper extends Context { 7 Context mBase; //該屬性指向一個ContextIml實例 8 9 public ContextWrapper(Context base) { 10 mBase = base; 11 } 12 13 /** 14 * Set the base context for this ContextWrapper. All calls will then be 15 * delegated to the base context. Throws 16 * IllegalStateException if a base context has already been set. 17 * 18 * @param base The new base context for this wrapper. 19 * 建立Application、Service、Activity,會調用該方法給mBase屬性賦值 20 */ 21 protected void attachBaseContext(Context base) { 22 if (mBase != null) { 23 throw new IllegalStateException("Base context already set"); 24 } 25 mBase = base; 26 } 27 28 @Override 29 public Looper getMainLooper() { 30 return mBase.getMainLooper(); 31 } 32 33 @Override 34 public Object getSystemService(String name) { 35 return mBase.getSystemService(name); 36 } 37 38 @Override 39 public void startActivity(Intent intent) { 40 mBase.startActivity(intent); 41 } 42 }
8、ContextThemeWrapper
該類內部包含了主題(Theme)相關的接口,即android:theme屬性指定的。只有Activity須要主題,Service不須要主題,因此Service直接繼承於ContextWrapper類
1 /** 2 * A ContextWrapper that allows you to modify the theme from what is in the 3 * wrapped context. 4 */ 5 public class ContextThemeWrapper extends ContextWrapper { 6 private Context mBase; 7 private int mThemeResource; 8 private Resources.Theme mTheme; 9 private LayoutInflater mInflater; 10 private Configuration mOverrideConfiguration; 11 private Resources mResources; 12 13 public ContextThemeWrapper() { 14 super(null); 15 } 16 17 public ContextThemeWrapper(Context base, int themeres) { 18 super(base); 19 mBase = base; 20 mThemeResource = themeres; 21 } 22 23 @Override protected void attachBaseContext(Context newBase) { 24 super.attachBaseContext(newBase); 25 mBase = newBase; 26 } 27 28 @Override public void setTheme(int resid) { 29 mThemeResource = resid; 30 initializeTheme(); 31 } 32 33 @Override public Resources.Theme getTheme() { 34 if (mTheme != null) { 35 return mTheme; 36 } 37 38 mThemeResource = Resources.selectDefaultTheme(mThemeResource, 39 getApplicationInfo().targetSdkVersion); 40 initializeTheme(); 41 42 return mTheme; 43 } 44 }
9、ActivityThread消息處理函數與本節相關內容以下
1 public void handleMessage(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 }
10、建立Application對象時建立Context實例
// ActivityThread.java private void handleBindApplication(AppBindData data) { try { // If the app is being launched for full backup or restore, bring it up in // a restricted environment with the base application class. Application app = data.info.makeApplication(data.restrictedBackupMode, null); mInitialApplication = app; ... } finally { StrictMode.setThreadPolicy(savedPolicy); } } // LoadedApk.java 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(); // 建立ContextImpl實例 appContext.init(this, null, mActivityThread); app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext); appContext.setOuterContext(app); // 將Application實例傳遞給Context實例 } catch (Exception e) { ... } mActivityThread.mAllApplications.add(app); mApplication = app; return app; } private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) { ContextImpl appContext = new ContextImpl(); // 建立ContextImpl實例 appContext.init(r.packageInfo, r.token, this); appContext.setOuterContext(activity); // For debugging purposes, if the activity's package name contains the value of // the "debug.use-second-display" system property as a substring, then show // its content on a secondary display if there is one. 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; }
11、建立Service對象時建立Context實例
經過startService或者bindService時,若是系統檢測到須要新建立一個Service實例,就會回調handleCreateService()方法,完成相關數據操做。handleCreateService()函數位於 ActivityThread.java類,以下
1 private void handleCreateService(CreateServiceData data) { 2 // If we are getting ready to gc after going to the background, well 3 // 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 new RuntimeException( 15 "Unable to instantiate service " + data.info.name 16 + ": " + 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 new RuntimeException( 41 "Unable to create service " + data.info.name 42 + ": " + e.toString(), e); 43 } 44 } 45 }
1 private void handleCreateService(CreateServiceData data) { 2 // If we are getting ready to gc after going to the background, well 3 // 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 new RuntimeException( 15 "Unable to instantiate service " + data.info.name 16 + ": " + 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 new RuntimeException( 41 "Unable to create service " + data.info.name 42 + ": " + e.toString(), e); 43 } 44 } 45 }