您好,登錄后才能下訂單哦!
這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)Android中Context的作用是什么,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
Context基本概念
Context是什么?
1) Context是一個(gè)抽象類,其通用實(shí)現(xiàn)在ContextImpl類中。
2) Context:是一個(gè)訪問(wèn)application環(huán)境全局信息的接口,通過(guò)它可以訪問(wèn)application的資源和相關(guān)的類,其主要功能如下:
啟動(dòng)Activity
啟動(dòng)和停止Service
發(fā)送廣播消息(Intent)
注冊(cè)廣播消息(Intent)接收者
可以訪問(wèn)APK中各種資源(如Resources和AssetManager等)
可以訪問(wèn)Package的相關(guān)信息
APK的各種權(quán)限管理
從以上分析可以看出,Context就是一個(gè)對(duì)APK包無(wú)所不知的大管家,大家需要什么,直接問(wèn)它就可以了。
Context與View的關(guān)系
View與Context(或Activity)的關(guān)系類似于明星與經(jīng)紀(jì)人的關(guān)系,所以創(chuàng)建View時(shí),必須明確指定其Context(即經(jīng)紀(jì)人或大管家),否則View就成不了明星。
Context家族關(guān)系
Context關(guān)鍵函數(shù)
public abstract class Context { // 獲取應(yīng)用程序包的AssetManager實(shí)例 public abstract AssetManager getAssets(); // 獲取應(yīng)用程序包的Resources實(shí)例 public abstract Resources getResources(); // 獲取PackageManager實(shí)例,以查看全局package信息 public abstract PackageManager getPackageManager(); // 獲取應(yīng)用程序包的ContentResolver實(shí)例 public abstract ContentResolver getContentResolver(); // 它返回當(dāng)前進(jìn)程的主線程的Looper,此線程分發(fā)調(diào)用給應(yīng)用組件(activities, services等) public abstract Looper getMainLooper(); // 返回當(dāng)前進(jìn)程的單實(shí)例全局Application對(duì)象的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); } // 返回一個(gè)可用于獲取包中類信息的class loader public abstract ClassLoader getClassLoader(); // 返回應(yīng)用程序包名 public abstract String getPackageName(); // 返回應(yīng)用程序信息 public abstract ApplicationInfo getApplicationInfo(); // 根據(jù)文件名獲取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); // 返回應(yīng)用程序obb文件路徑 public abstract File getObbDir(); // 啟動(dòng)一個(gè)新的activity public abstract void startActivity(Intent intent); // 啟動(dòng)一個(gè)新的activity public void startActivityAsUser(Intent intent, UserHandle user) { throw new RuntimeException("Not implemented. Must override in a subclass."); } // 啟動(dòng)一個(gè)新的activity // intent: 將被啟動(dòng)的activity的描述信息 // options: 描述activity將如何被啟動(dòng) public abstract void startActivity(Intent intent, Bundle options); // 啟動(dòng)多個(gè)新的activity public abstract void startActivities(Intent[] intents); // 啟動(dòng)多個(gè)新的activity public abstract void startActivities(Intent[] intents, Bundle options); // 廣播一個(gè)intent給所有感興趣的接收者,異步機(jī)制 public abstract void sendBroadcast(Intent intent); // 廣播一個(gè)intent給所有感興趣的接收者,異步機(jī)制 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); // 注冊(cè)一個(gè)BroadcastReceiver,且它將在主activity線程中運(yùn)行 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); // 請(qǐng)求啟動(dòng)一個(gè)application service public abstract ComponentName startService(Intent service); // 請(qǐng)求停止一個(gè)application service public abstract boolean stopService(Intent service); // 連接一個(gè)應(yīng)用服務(wù),它定義了application和service間的依賴關(guān)系 public abstract boolean bindService(Intent service, ServiceConnection conn, int flags); // 斷開(kāi)一個(gè)應(yīng)用服務(wù),當(dāng)服務(wù)重新開(kāi)始時(shí),將不再接收到調(diào)用, // 且服務(wù)允許隨時(shí)停止 public abstract void unbindService(ServiceConnection conn); // 返回系統(tǒng)級(jí)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); // 返回一個(gè)新的與application name對(duì)應(yīng)的Context對(duì)象 public abstract Context createPackageContext(String packageName, int flags) throws PackageManager.NameNotFoundException; // 返回基于當(dāng)前Context對(duì)象的新對(duì)象,其資源與display相匹配 public abstract Context createDisplayContext(Display display); }
ContextImpl關(guān)鍵成員和函數(shù)
/** * Common implementation of Context API, which provides the base * context object for Activity and other application components. */ 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>(); /*package*/ LoadedApk mPackageInfo; // 關(guān)鍵數(shù)據(jù)成員 private String mBasePackageName; private Resources mResources; /*package*/ 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); } }
ContextWrapper
它只是對(duì)Context類的一種封裝,它的構(gòu)造函數(shù)包含了一個(gè)真正的Context引用,即ContextImpl對(duì)象。
/** * Proxying implementation of Context that simply delegates all of its calls to * another Context. Can be subclassed to modify behavior without changing * the original Context. */ public class ContextWrapper extends Context { Context mBase; //該屬性指向一個(gè)ContextIml實(shí)例 public ContextWrapper(Context base) { mBase = base; } /** * Set the base context for this ContextWrapper. All calls will then be * delegated to the base context. Throws * IllegalStateException if a base context has already been set. * * @param base The new base context for this wrapper. * 創(chuàng)建Application、Service、Activity,會(huì)調(diào)用該方法給mBase屬性賦值 */ 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); } }
ContextThemeWrapper
該類內(nèi)部包含了主題(Theme)相關(guān)的接口,即android:theme屬性指定的。只有Activity需要主題,Service不需要主題,所以Service直接繼承于ContextWrapper類。
/** * A ContextWrapper that allows you to modify the theme from what is in the * wrapped context. */ 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; } }
何時(shí)創(chuàng)建Context
應(yīng)用程序在以下幾種情況下創(chuàng)建Context實(shí)例:
1) 創(chuàng)建Application 對(duì)象時(shí), 而且整個(gè)App共一個(gè)Application對(duì)象
2) 創(chuàng)建Service對(duì)象時(shí)
3) 創(chuàng)建Activity對(duì)象時(shí)
因此應(yīng)用程序App共有的Context數(shù)目公式為:
總Context實(shí)例個(gè)數(shù) = Service個(gè)數(shù) + Activity個(gè)數(shù) + 1(Application對(duì)應(yīng)的Context實(shí)例)
ActivityThread消息處理函數(shù)與本節(jié)相關(guān)的內(nèi)容如下:
public void handleMessage(Message msg) { if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); switch (msg.what) { case LAUNCH_ACTIVITY: { // 創(chuàng)建Activity對(duì)象 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: // 創(chuàng)建Application對(duì)象 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: // 創(chuàng)建Service對(duì)象 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate"); handleCreateService((CreateServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case BIND_SERVICE: // Bind Service對(duì)象 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind"); handleBindService((BindServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; } }
創(chuàng)建Application對(duì)象時(shí)創(chuàng)建Context實(shí)例
每個(gè)應(yīng)用程序在***次啟動(dòng)時(shí),都會(huì)首先創(chuàng)建一個(gè)Application對(duì)象。從startActivity流程可知,創(chuàng)建Application的時(shí)機(jī)在handleBindApplication()方法中,該函數(shù)位于 ActivityThread.java類中 ,相關(guān)代碼如下:
// 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(); // 創(chuàng)建ContextImpl實(shí)例 appContext.init(this, null, mActivityThread); app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext); appContext.setOuterContext(app); // 將Application實(shí)例傳遞給Context實(shí)例 } catch (Exception e) { ... } mActivityThread.mAllApplications.add(app); mApplication = app; return app; }
創(chuàng)建Activity對(duì)象時(shí)創(chuàng)建Context實(shí)例
通過(guò)startActivity()或startActivityForResult()請(qǐng)求啟動(dòng)一個(gè)Activity時(shí),如果系統(tǒng)檢測(cè)需要新建一個(gè)Activity對(duì)象時(shí),就會(huì)回調(diào)handleLaunchActivity()方法,該方法繼而調(diào)用performLaunchActivity()方法,去創(chuàng)建一個(gè)Activity實(shí)例,并且回調(diào)onCreate(),onStart()方法等,函數(shù)都位于 ActivityThread.java類 ,相關(guān)代碼如下:
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); // 創(chuàng)建Context 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(); // 創(chuàng)建ContextImpl實(shí)例 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; }
創(chuàng)建Service對(duì)象時(shí)創(chuàng)建Context實(shí)例
通過(guò)startService或者bindService時(shí),如果系統(tǒng)檢測(cè)到需要新創(chuàng)建一個(gè)Service實(shí)例,就會(huì)回調(diào)handleCreateService()方法,完成相關(guān)數(shù)據(jù)操作。handleCreateService()函數(shù)位于 ActivityThread.java類,如下:
private void handleCreateService(CreateServiceData data) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. 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(); // 創(chuàng)建ContextImpl實(shí)例 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) { // nothing to do. } } catch (Exception e) { if (!mInstrumentation.onException(service, e)) { throw new RuntimeException( "Unable to create service " + data.info.name + ": " + e.toString(), e); } } }
上述就是小編為大家分享的Android中Context的作用是什么了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。