Android Context類

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 }
相關文章
相關標籤/搜索