博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android Context类
阅读量:7063 次
发布时间:2019-06-28

本文共 16282 字,大约阅读时间需要 54 分钟。

一、Context类的使用场景

  ①、创建Application对象时,而且整个app公用一个Application对象

  ②、创建Service对象时

  ③、创建Activity对象时

二、应用程序共有几个Context的公式

  ①、  Context(总)=Context(service个数)+Context(activity个数)+1(一个application对象)

三、Context概念

 

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

  ②、Context是维持Android程序中各组件能过正常工作的一个核心功能类,开发中称:上下文

 

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

 

    1)、启动Activity

    2)、启动和停止Service
    3)、发送广播消息(Intent)
    4)、注册广播消息(Intent)接收者
    5)、可以访问APK中各种资源(如Resources和AssetManager等)
    6)、可以访问Package的相关信息
    7)、APK的各种权限管理

四、Context的继承

     ①、ContextIML(mPackageInfo)和ContextWrapper(mBase : Context)都继承自Context

     ②、Context API的通用实现,他为Activity和其他application组件提供基本的context对象

     ③、Context代理实现,他简单地把调用请求发送给另一个context

     ④、service、contextThemeWrapper、application皆继承自contextWrapper,activity继承自contextThemeWrapper

 

五、关键函数

 

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对象的Contextpublic 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 loaderpublic abstract ClassLoader getClassLoader();// 返回应用程序包名public abstract String getPackageName();// 返回应用程序信息public abstract ApplicationInfo getApplicationInfo();// 根据文件名获取SharedPreferencespublic 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();// 启动一个新的activitypublic abstract void startActivity(Intent intent);// 启动一个新的activitypublic 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);// 启动多个新的activitypublic abstract void startActivities(Intent[] intents);// 启动多个新的activitypublic 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 servicepublic abstract ComponentName startService(Intent service);// 请求停止一个application servicepublic 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);}

 

六、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
sSharedPrefs =10 new HashMap
();11 12 /*package*/ LoadedApk mPackageInfo; // 关键数据成员13 private String mBasePackageName;14 private Resources mResources;15 /*package*/ ActivityThread mMainThread; // 主线程16 17 @Override18 public AssetManager getAssets() {19 return getResources().getAssets();20 }21 22 @Override23 public Looper getMainLooper() {24 return mMainThread.getLooper();25 }26 27 @Override28 public Object getSystemService(String name) {29 ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);30 return fetcher == null ? null : fetcher.getService(this);31 }32 33 @Override34 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 }

 

七、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 be15 * delegated to the base context.  Throws16 * 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 @Override29 public Looper getMainLooper() {30 return mBase.getMainLooper();31 }32 33 @Override34 public Object getSystemService(String name) {35 return mBase.getSystemService(name);36 }37 38 @Override39 public void startActivity(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 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 }

九、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 } 十、创建Application对象时创建Context实例
// ActivityThread.javaprivate 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.javapublic 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;}

十一、创建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.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 new RuntimeException(41 "Unable to create service " + data.info.name42 + ": " + 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.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 new RuntimeException(41 "Unable to create service " + data.info.name42 + ": " + e.toString(), e);43 }44 }45 }

 

 

转载于:https://www.cnblogs.com/SM-Elephant/p/9809041.html

你可能感兴趣的文章
android broadcastreceiver
查看>>
[转] 关于幂律分布的一个笔记
查看>>
Python import 指定目录中的模块
查看>>
7种方法来创业
查看>>
前端面试技巧与技术栈准备梳理
查看>>
Controller
查看>>
1031 Hungar的得分问题(二)
查看>>
软件工程 第一个小例子
查看>>
X86 Booting Sequence
查看>>
python中xrange和range的异同
查看>>
服务器端升级为select模型处理多客户端
查看>>
IOC容器实例化过程
查看>>
android起源
查看>>
网页结构与表现原则
查看>>
MATLAB读取CCS保存的数据
查看>>
Java superArray2
查看>>
这几道Java集合框架面试题在面试中几乎必问
查看>>
HDU4545:魔法串(DP)
查看>>
协程补充
查看>>
ASS字幕制作和压制教程
查看>>