Android Context类
一、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对象的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); }
六、ContextIML关键成员以及函数
/** * 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; // 关键数据成员 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
它只是对Context类的一种封装,它的构造函数包含了一个真正的Context引用,即ContextImpl对象
/** * 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; //该属性指向一个ContextIml实例 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. * 创建Application、Service、Activity,会调用该方法给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
该类内部包含了主题(Theme)相关的接口,即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; } }
九、ActivityThread消息处理函数与本节相关内容如下
public void handleMessage(Message msg) { if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); switch (msg.what) { case LAUNCH_ACTIVITY: { // 创建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: // 创建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: // 创建Service对象 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对象 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind"); handleBindService((BindServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; } }十、创建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; }
十一、创建Service对象时创建Context实例
通过startService或者bindService时,如果系统检测到需要新创建一个Service实例,就会回调handleCreateService()方法,完成相关数据操作。handleCreateService()函数位于 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(); // 创建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) { // nothing to do. } } catch (Exception e) { if (!mInstrumentation.onException(service, e)) { throw new RuntimeException( "Unable to create service " + data.info.name + ": " + e.toString(), e); } } }
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(); // 创建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) { // 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类的更多相关文章
- Android开发中Context类的作用以及Context的详细用法
Android中Context的作用以及Context的详细用法 本文我们一起来探讨一下关于Android中Context的作用以及Context的详细用法,这对我们学习Android的资源访问有很大 ...
- Android开发——Context类的各种细节问题
0. 前言 Context相信所有的Android开发人员基本上每天都在接触,因为它太常见了.但实际上Context有太多小的细节并不被大家所关注,那么今天我们就来学习一下那些你所不知道的细节. ...
- Android 服务类Service 的详细学习
http://blog.csdn.net/vipzjyno1/article/details/26004831 Android服务类Service学习四大组建 目录(?)[+] 什么是服务 服务有 ...
- Android Context 是什么?
andorid 开发(42) 版权声明:本文为博主原创文章,未经博主允许不得转载. [转载请注明出处:http://blog.csdn.net/feiduclear_up CSDN 废墟的树] PS ...
- Android Context创建过程
特定的资源或者类构成了Android应用程序的运行上下文环境 PackageManager, ClassLoader, Assert等等 Android应用程序窗口的运行上下文环境是通过Con ...
- 源码心德`Context`类
Context,中文直译为“上下文”,SDK中对其说明如下: Interface to global information about an application environment. Thi ...
- Android 服务类Service 的具体学习
上一篇说到了通知栏Notification,提起通知栏,不得让人想到Service以及BroadcastReceive,作为android的4大组建的2个重要成员,我们没少和它们打交道.它们能够在无形 ...
- Android Context讲解(转)
博客出处 前言:本文是我读<Android内核剖析>第7章 后形成的读书笔记 ,在此向欲了解Android框架的书籍推荐此书. 大家好, 今天给大家介绍下我们在应用开发中最熟悉而陌生的朋友 ...
- 【42】android Context深度剖析
android程序和java程序的区别 Android程序不像Java程序一样,随便创建一个类,写个main()方法就能跑了,而是要有一个完整的Android工程环境,在这个环境下,我们有像Activ ...
随机推荐
- 第五篇: 路由网关(zuul)
在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统. 在Spring Cloud ...
- asp.net mvc 安全测试漏洞 "跨站点请求伪造" 问题解决
IBM Security Appscan漏洞筛查-跨站请求伪造,该漏洞的产生,有多种情况: 1.WebApi的跨站请求伪造,需要对WebApi的请求头部做限制(此文不做详细介绍): 2.MVC Act ...
- OpenCL科普及在ubuntu 16.04 LTS上的安装
OpenCL(Open Computing Language,开放计算语言)是一个为异构平台编写程序的框架,此异构平台可由CPU.GPU.DSP.FPGA或其他类型的处理器與硬體加速器所组成.Open ...
- Docker部署Vue 工程包
docker部署 Vue 工程包 目录结构 [root@host ~]# tree front/ front/ ├── dist.conf ├── dist.zip ├── Dockerfile └─ ...
- 14-使用glusterfs做持久化存储
使用glusterfs做持久化存储 我们复用kubernetes的三台主机做glusterfs存储. 以下步骤参考自:https://www.xf80.com/2017/04/21/kubernete ...
- List通过HashSet去重
//JAVA中//使用hashset去重复,set为重复的集合,可以通过new ArrayList(set)转换成list HashSet<HashMap<String, String&g ...
- Python内置类型(4)--数值
Python有以下三种的数值类型: 整型(integers), 浮点型(floating point numbers), 以及 复数(complex numbers).此外,布尔是整数的子类型. 数值 ...
- python虚拟环境 | virtualenv 的简单使用 (图文)
一.创建virtualenv虚拟环境 mkvirtualenv -p 版本号 虚拟名 mkvirtualenv -p python3 env_1 python3:版本号 env_1: 虚拟环境名称 创 ...
- 【Shell实战】批量在多台服务器上执行命令
功能说明:批量在多台服务器上执行命令 #!/bin/bash # ========================================== # 功能:批量在多台服务器上执行命令 # 方法: ...
- IdentityServer4 中文文档 -6- (简介)示例服务器和测试
IdentityServer4 中文文档 -6- (简介)示例服务器和测试 原文:http://docs.identityserver.io/en/release/intro/test.html 目 ...