Context派生了ContextWrapper派生了ContextThemeWrapper派生了Activity,这个是为什么要先从Context来分析。
那就大致说说Context类的主要的功能和属性吧:
属性包含:
1.打开文件模式的属性。(文件系统,数据库等)
2.绑定服务模式的属性。
3.得到系统服务的所有名字的属性。(凡是支持的服务,都可以通过getSystemService(String name)获得)
4.创建Context的标识属性。(暂时没发现它的用途)
方法包含:
1.获取应用包资源的实例。(assets,resources,PackageManager,ContentResolver等)。
2.获取主线程Looper。
public abstract Looper getMainLooper();
返回当前主线程中的Looper。用于调度的线程调用应用程序组件
3.获取应用(Application)的Context。
public abstract Context getApplicationContext();
返回单例的Context。
如果当前使用的是Activity的Context,接收方法将被注册在这个Activity中,这意味这在Activity销毁之前将会被注销。实际上,当系统框架在销毁Activity时,即使你什么也没做,也会清除你的绑定,并会报错。因此,当你用Activity的Context绑定一个静态广播时,它会随着Activity销毁而销毁;
如果当前使用这个方法返回的Context,将会得到一个全局的Context。但是,使用时也需要注意,因为如果当你用它绑定广播或其它组件而没有解除绑定的话,很容易造成内存泄露。
这意味着需要看情况而选择使用Activity的Context还是Application的Context。
4.注册和移除注册组件的回调。
1.registerComponentCallbacks(ComponentCallbacks callback)
2.unregisterComponentCallbacks(ComponentCallbacks callback)
这里就需要提一下关于Android组件的内存管理模块了
OnLowMemory
OnLowMemory是Android提供的API,在系统内存不足,所有后台程序(优先级为background的进程,不是指后台运行的进程)都被杀死时,系统会调用OnLowMemory。系统提供的回调有:Application/Activity/Fragementice/Service/ContentProvider
除了上述系统提供的API,还可以自己实现ComponentCallbacks,通过API注册,这样也能得到OnLowMemory回调。例如:
public static class MyCallback implements ComponentCallbacks {
@Override
public void onConfigurationChanged(Configuration arg) {
}
@Override
public void onLowMemory() {
//do release operation
}
}
然后,通过Context.registerComponentCallbacks ()在合适的时候注册回调就可以了。通过这种自定义的方法,可以在很多地方注册回调,而不需要局限于系统提供的组件。
2. OnTrimMemory
OnTrimMemory是Android 4.0之后提供的API,系统会根据不同的内存状态来回调。系统提供的回调有:Application/Activity/Fragement/Service/ContentProvider
OnTrimMemory的参数是一个int数值,代表不同的内存状态:
TRIM_MEMORY_COMPLETE:内存不足,并且该进程在后台进程列表最后一个,马上就要被清理
TRIM_MEMORY_MODERATE:内存不足,并且该进程在后台进程列表的中部。
TRIM_MEMORY_BACKGROUND:内存不足,并且该进程是后台进程。
TRIM_MEMORY_UI_HIDDEN:内存不足,并且该进程的UI已经不可见了。 以上4个是4.0增加
TRIM_MEMORY_RUNNING_CRITICAL:内存不足(后台进程不足3个),并且该进程优先级比较高,需要清理内存
TRIM_MEMORY_RUNNING_LOW:内存不足(后台进程不足5个),并且该进程优先级比较高,需要清理内存
TRIM_MEMORY_RUNNING_MODERATE:内存不足(后台进程超过5个),并且该进程优先级比较高,需要清理内存
以上3个是4.1增加系统也提供了一个ComponentCallbacks2,通过Context.registerComponentCallbacks()注册后,就会被系统回调到。
OnLowMemory和OnTrimMemory的比较
1,OnLowMemory被回调时,已经没有后台进程;而onTrimMemory被回调时,还有后台进程。
2,OnLowMemory是在最后一个后台进程被杀时调用,一般情况是low memory killer 杀进程后触发;而OnTrimMemory的触发更频繁,每次计算进程优先级时,只要满足条件,都会触发。
3,通过一键清理后,OnLowMemory不会被触发,而OnTrimMemory会被触发一次。
5.从应用包中获取默认的字符串。
6.设置和获取Context的主题。
7.获取样式属性。
TypedArray obtainStyledAttributes ( int[] attrs ) ;
TypedArray obtainStyledAttributes ( int resid, int[] attrs );
TypedArray obtainStyledAttributes ( AttributeSet set, int[] attrs );
TypedArray obtainStyledAttributes ( AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes );
8.获取类加载器,包名,context的包的全部应用信息。
9.获取文件(内部和外部存储)操作的一些方法,包含:文件,数据库,shareperference等。
10.对墙纸wallperper的操作的方法。
11.启动Activity的方法。
void startActivity( Intent intent );
void startActivity( Intent intent, Bundle options );
两个方法的启动流程是相同的;
需要注意的是,当你在非Activity中启动一个新的Activity时,需要在 Intent 中添加 FLAG_ACTIVITY_NEW_TASK。原因是当Activity不是从一个现有的Activity 中启动时,就没有一个现有的 Task 来放置它,所以需要一个新的 Task。
如果调用此方法时,没有找到启动它的Activity,将会报 ActivityNotFoundException 错误。
void startActivities( Intent[] intents );
void startActivities( Intent[] intents, Bundle options );
流程同上面两个方法,从字面上可以看出是启动多个Activity;
void startActivityAsUser( Intent intent, UserHandle user );
void startActivityAsUser( Intent intent, Bundle options, UserHandle userId );
void startActivitiesAsUser( Intent[] intents, Bundle options, UserHandle userHandle );
这三个方法没有仔细研究。
void startIntentSender( IntentSender intent,Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags );
void startIntentSender( IntentSender intent, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
Bundle options ) ;
12.发送广播,注册和取消注册接收器的方法。
void sendBroadcast( Intent intent );
发送 Intent 给所有对此感兴趣的 BroadcastReceiver。这个方法是异步的。
void sendBroadcast( Intent intent, String receiverPermission );
这个方法与上一个方法不同之处在于,这个方法可以添加一个权限来执行,
void sendOrderedBroadcast( Intent intent,String receiverPermission );
这个方法与sendBroadcase() 不同之处在于 sendBroadcase() 是用来广播无序事件,即所有的接收者在理论上是同时接收到事件,同时执行的,对消息传递的效率而言这是比较好的做法。而此方法用来向系统广播有序事件(Ordered broadcast),接收者按照在Manifest.xml文件中设置的接收顺序依次接收Intent,顺序执行的,接收的优先级可以在系统配置文件中设置(声明在intent-filter元素的android:priority属性中,数值越大优先级别越高,其取值范围为-1000到1000。当然也可以在调用IntentFilter对象的setPriority()方法进行设置)。对于有序广播而言,前面的接收者可以对接收到得广播意图(Intent)进行处理,并将处理结果放置到广播意图中,然后传递给下一个接收者,当然前面的接收者有权终止广播的进一步传播。如果广播被前面的接收者终止后,后面的接收器就再也无法接收到广播了。
void sendOrderedBroadcast( Intent intent, String receiverPermission, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData, Bundle initialExtras );此方法与上一个方法的不同参数在于 此方法允许你接收从广播中返回的数据。
void sendBroadcastAsUser( Intent intent, UserHandle user );
void sendBroadcastAsUser( Intent intent, UserHandle user,String receiverPermission );
void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras);
这三个方法与多用户操作有关,目前没有研究。
void sendStickyBroadcast( Intent intent );
void sendStickyOrderedBroadcast( Intent intent,BroadcastReceiver resultReceiver,Handler scheduler, int initialCode,
String initialData,Bundle initialExtras );
这两个方法发出的广播会一直滞留(等待),以便有人
注册这则广播消息后能尽快的收到这条广播。其他功能与sendBroadcast相同。但是使用sendStickyBroadcast 发送广播需要获得
BROADCAST_STICKY
permission,如果没有这个permission则会抛出异常。
Intent registerReceiver( BroadcastReceiver receiver,IntentFilter filter );
在一个运行中的Activity注册广播接收器,当接收到过滤后的广播时,接收者将被Call。
系统可能广播“sticku”(粘性的)Intent,这样Intent将会一直存在,直到广播结束,这样可以发送给其他推迟注册的广播,如果你的IntentFilter匹配一个粘性的Intent,这个Intent将会返回,即该方法返回类型为Intent,注册接收器将返回这个Intent。
可能会有多个黏性的匹配的 Intent 发送到注册的接收器,这种情况下只会返回一个Intent,这将决定与系统。
如果你知道你接收的 Intent 是粘性的,你可以提供null给接收者,这种情况下,没有接收器注册,该方法仅返回匹配的粘性 Intent。在多个Intent匹配的情况下,可以使用上述方法。
注意:该方法不能在一个BroadcaseReceiver组件中声明,这是因为,BroadcaseReceiver是从一个Application的mainifest中公开的。然而,在一个本身被注册并且正在运行的 BroadcaseReceiver 中调用该方法,这样会出错。。。
Intent registerReceiver(BroadcastReceiver receiver,
IntentFilter filter, String broadcastPermission, Handler scheduler);
注册一个广播接收器,在Hanlder中运行,这允许你执行permissions来设置谁能接受到广播,或接受方运行在一个非主线程的线程中。
Intent registerReceiverAsUser(BroadcastReceiver receiver,UserHandle user, IntentFilter filter,
String broadcastPermission,Handler scheduler );
void unregisterReceiver(BroadcastReceiver receiver);
解除绑定
13.启动和停止,绑定服务的方法。
ComponentName startService(Intent service);
请求启动给定的应用程序 Service。Intent 即可以包含完整的 Service 包名,也可以通过一个抽象的定义在其他域的 action 来启动 Service。如果该 Service 没有运行,将会被实例化并且开始运行(如需要,将会为它创建一个进程),如果该 Service 正在运行,那么它将继续运行下去。
每次调用该方法,将会调用 Intent 中给出的 Service 的相应方法。这提供了一个方便的方式去提交工作到一个 没有绑定和调用自己接口的Service 中。
使用这个方法可以重写一个默认被 bindService() 启动的 Service 的生命周期。不管任何客户端连接到它,如果没有调用 stopService() 方法,它会一直运行下去。
System 可能会一直保持运行,直到系统内存不足时,它将会被 kill 掉,如果运行过程中发生异常,Service 将会自动重启。
如果你没有权限启动 Service ,这个方法将会抛出 SecurityException 错误。
boolean stopService(Intent service);
请求停止一个给定的 Service。如果该 Service 没有运行,将不做任何操作,否则,这个 Service 就会停止运行。需要注意的是,调用 startService() 是不被计数的,也就是说不管以前调用多少次 startServce() ,只要调用 stopService() 后,该 Service 就会停止运行。
ComponentName startServiceAsUser(Intent service, UserHandle user);
boolean stopServiceAsUser(Intent service, UserHandle user);
bindService(Intent service, ServiceConnection conn, int flags);
如果需要,将会链接一个应用 Service。这将会定义您的应用程序与 Service 之间的依赖关系,给定的链接将会接受到 Service 创建和结束时的信息。只有调用的 Context 存在,该 Service 才会被系统认可。例如,如果这是个 Activity 的 Context,当这个Activity 结束后,这个Service 也会随之停止运行,直到这个 Activity 重启后,该 Service 才会继续运行。
如果你没有权限启动 Service ,这个方法将会抛出 SecurityException 错误。
需要注意的是,该方法不能在一个 BroadcaseReceiver 组件中调用。
void unbindService( ServiceConnection conn );
取消绑定Service。
14.启动仪器的方法。
15.获取系统服务。
Object getSystemService(String name);
16.检查,执行权限的方法。
PERMESSION_GRANTED = 0 允许标识;
PERMESSION_DENIED = -1 不允许标识;
int checkPermission(String permission, int pid, int uid);检测给定的权限是否可以在特定的进程中运行,是则返回0,否则返回-1.
int checkCallingPermission(String permission);
这个方法和上个方法基本上一致,但是当前线程如果不是一个IPC线程,这个方法就不能用,
int checkCallingOrSelfPermission(String permission);
这个方法和上个方法也基本一致,区别是它有自己的权限,如果当前进程不是IPC,请谨慎使用该方法。
void enforcePermission( String permission, int pid, int uid, String message);
执行权限。但如果你给定的权限不允许在给定的进程中运行的话,将会报 SecurityException 错。
void enforceCallingPermission( String permission, String message);
与上方法基本一致。
void enforceCallingOrSelfPermission( String permission, String message);
与上方法基本一致。
void grantUriPermission(String toPackage, Uri uri, int modeFlags);
通过一个赋予权限的特定Url来访问另一个包,不管这个包是否提供了内部访问Url,这可以用于授权特定的、临时的权限,通常用于相应用户的交互,比如用户打卡一个你想要显示其他东西的页面
这种机制允许一个公用的功能性模型使用户相互交互(打开一个附件,从一个列表中选择一个联系人,等等)驱动ad-hoc在优粒度权限的许可下。这可能是一个主要设备,应用程序为了减少这个权限而需要,仅仅直接关系到它们的行为。 这优粒度URI权限的许可工作,然而,请求一些协作和内容提供者保持那些URI。强烈推荐内容提供者实现这种设备,并且通过android:grantUriPermissions 属性或者 <grant-uri-permissions> 标签声明支持它。
void revokeUriPermission(Uri uri, int modeFlags);
删除特定Url中的所有权限,
int checkUriPermission(Uri uri, int pid, int uid, int modeFlags);
int checkCallingOrSelfUriPermission(Uri uri, int modeFlags);
int checkCallingOrSelfUriPermission(Uri uri, int modeFlags);
检查特定的进程或PID是否有权限访问特定的Url,这仅仅能检查显示权限,如果给定的进程/PID 有更普通的方法能访问Url所指向的内容提供者,这个方法将会失败。
void enforceUriPermission( Uri uri, int pid, int uid, int modeFlags, String message);
void enforceCallingUriPermission( Uri uri, int modeFlags, String message);
void enforceCallingOrSelfUriPermission( Uri uri, int modeFlags, String message);
void enforceUriPermission( Uri uri, String readPermission, String writePermission, int pid, int uid, int modeFlags, String message);
内容同上。
17.创建Context的方法。
Context createPackageContext(String packageName,int flags)
生成一个给定应用名称的新Context。这个Context与给定的应用程序启动后的Context相同,有相同的资源和类加载器。每次调用此方法就会返回一个新的Context实例,Context对象是不共享的,但他们有共同的状态,所以,Context本身是轻量级的。
Context createPackageContextAsUser( String packageName, int flags, UserHandle user);
同上方法,指定用户。
Context createConfigurationContext( Configuration overrideConfiguration);
生成一个特定配置的Context对象,其他同上。
Context createDisplayContext(Display display);
生成一个特定资源的Context对象。其他同上
18.获取兼容性信息和检查是否受限的方法。
CompatibilityInfoHolder getCompatibilityInfo(int displayId);