1,Context类
Context是维持Android应用的核心功能类,是整个Android系统交互的核心。是个抽象类。
Context是个抽象类,它的具体实现类是ContextImpl,ContextWrapper是个包装类,内部的成员变量mBase指向的也是个ContextImpl对象,ContextImpl完成了
实际的功能,Activity、Service与Application都直接或者间接的继承ContextWrapper。
Broadcast Receiver,Content Provider并不是Context的子类,他们所持有的Context都是其他地方传过去的,所以并不计入Context总数。
1)ContextWrapper
是Context的封装类。透明的经典的装饰模式。
这是一个Context的包装器,里面包含了一个mBase。
ContextWrapper有三个直接的子类:ContextThemeWrapper、Service和Application。
Android里面也有MockContext,但那是用来测试的,这个地方也可以看作是用了策略的思想,但正常运行的时候是主要是侧重于不同的装饰。这其实也是装饰的好处。
2)ContextImpl
这个是真正实现Context的类。
每一个Activity和Service以及Application的Context都是一个新的ContextImpl对象。
尽管Application、Activity、Service都有自己的ContextImpl,并且每个ContextImpl都有自己的mResources成员,但是由于它们的mResources成员都来自于唯一的ResourcesManager实例,所以它们看似不同的mResources其实都指向的是同一块内存。
Activity在创建的时候会new一个ContextImpl对象并在attach方法中关联它,Application和Service也差不多。ContextWrapper的方法内部都是转调ContextImpl的方法。
Context是为应用环境类,它包含了跟环境相关的各种操作:
①getResource(返回资源管理)
包含了getAssets,layout, string,drawable等等。
i>Android的资源框架:
- 根据layout,values,drawable等生成对应的ID,保存在R.id文件下面,而Android自带的资源在com.android.R.id里面。assets不会赋予id。
- Android用不同的资源目录后缀来适配不同的语言环境,屏幕大小,比如说drawable-en-w360。Android有一个对应的表,按照顺序匹配,对于drawable,本着不超过对应手机的参数的最大值来匹配。Android在打包的时候会将根据这些参数建立一个索引。
- 打包到resources.arsc文件中
ii>运行的时候应用读取过程
- 先去掉跟手机环境完全不匹配的资源目录,比如现在是中文环境,则去掉en目录
- assets由AssetsManager来访问。其他对应的资源根据MMC表的顺序,按照索引表一个一个的维度来匹配,筛选,直到找到对应的资源。如果没有找到则抛出异常。
②getPackageManager(返回包管理器)
包管理器可以管理安装在系统中的应用程序包相关的各种信息。
可以添加权限,可以查看对应包名的包信息,指定组件的组件信息,安装应用包等等。
Android里面不同的应用程序包名不同,包就对应了应用程序。所以从这里去理解PackageManager,他就是管理涉及到包管理(应用级相关的信息处理)的管理器。
③Service
Service除了包含startService,stopService,bindService,unbindService。
Service最终也是在ActivityManagerService中管理,但是Service不同的,在ActivityManagerService里面管理的是是ActiveServices。但是最终控制Service的流程还是会到达Handler中。
④registerBroadcast/unregisterBroadcast/sendBroadcast(Broadcast相关)
Context中有sendBroadcast, registerReceiver, unregisterReceiver。对应的都会通过ActivityManagerNative调用ActivityManagerService的相关函数。
broadcastIntent是处理sendBroadcast的, ActivityManagerService中也有registerReceiver, unregisterReceiver。ActivityManagerService里面保存有一个Broadcast的ReceiverList,注册的时候将Receiver保存起来,发送广播的时候,根据保存的IntentFilter来找到对应Receiver,另外BroadCastReceiver还有sticky,是注册的时候如果符合已有的sticky广播,则立刻发送给Receiver。
⑤getContentResolver(用于获取内容模型)
ContentResolver是用于获取Content模型的。
如:访问ContentProvider。
⑥startActivity(启动Activity);
Context包含了Activity的启动操作,Activity的启动过程简单来说就是经过下面几个步骤:
i>mMainThread.instrumentation.execStartActivity
mMainThread是ActivityThread类型,它管理着应用程序主线程的执行,像调度Activity,Broadcast等,instrumentation是一个Instrumentation类型,他是Android测试框架,在这里是为了监控Activity的活动,里面会有一个ActivityMonitor去监控被调用的Activity,用ActivityMonitor也可以等待一个指定的Activity启动。也可以阻止一个Activity的启动。
通过这种方式启动Activity主要就是为了监控Activity的启动活动,在测试中将会大有用处。启动完后,也可以检查启动后的返回组件信息。
ii>在execStartActivity的函数中,进行完监控后,就是通过ActivityManagerNative来启动指定的Activity。
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
看到Native其实就可以想到它是通过一种IPC机制来访问的了,具体是ActivityManagerProxy通过Binder进行IPC。
由Binder机制来访问ActivityManagerService,ActivityManagerService是进行Activity,Service, Broadcast管理的核心服务。
由ActivityManagerService.startActivity 会经过mStackSupervisor 以及 ActivityStack 进行相关处理
然后经过ApplicationThread, 最后到主线程的Handler(H)启动Activity
2,Application类
1)概念
每一个应用都会有一个Application。
Android源码中已经有的Application有EmailApplication,LauncherApplication, Browser等等。
2)作用
①多个组件之间数据共享
两个Activity之间数据共享。getApplication().方法名();
②做APP的全局初始化工作
比如图片加载框架的全局配置信息设置。
3)方法
4)生命周期
一个安装的应用对应一个LoadedApk对象,对应一个Application对象,对于四大组件,Application的创建和获取方式也是不尽相同的,具体说来:
Activity、Service:通过LoadedApk的makeApplication()方法创建。
静态广播:通过其回调方法onReceive()方法的第一个参数指向Application。
ContentProvider:无法获取Application,因此此时Application不一定已经初始化。
public class App extends Application {
@Override
public void onCreate() {
// 程序创建的时候执行
Log.d(TAG, "onCreate");
super.onCreate();
}
@Override
public void onTerminate() {
// 程序终止的时候执行
Log.d(TAG, "onTerminate");
super.onTerminate();
}
@Override
public void onLowMemory() {
// 低内存的时候执行
Log.d(TAG, "onLowMemory");
super.onLowMemory();
}
@Override
public void onTrimMemory(int level) {
// 程序在内存清理的时候执行
Log.d(TAG, "onTrimMemory");
super.onTrimMemory(level);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
Log.d(TAG, "onConfigurationChanged");
super.onConfigurationChanged(newConfig);
}
}
3,Application实现
1)在Manifest文件中指定Application的实现类
如果没有指定,系统会创建一个默认的Application类。
<application
android:name=".MyApplication"
……>
2)MyApplication具体实现
继承Application,实现是onCreate()方法。
public class MyApplicationextends Application {
private static MyApplication instance;
@Override
public void onCreate() {
super.onCreate();
instance = this;
}
public static MyApplicationextends getInstance(){
return instance;
}
}
4,注意
1)不能用Application缓存数据
因为Application会因为进入background后内存不足被系统干掉,进入后系统会重新创建一个Application类,而导致缓存在Application类里的数据全部初始化而丢失。
我们应该在Application中清除缓存。
2)错误的获取全局Context对象的方式
public class AnddroidApplication extends Application {
private static AnddroidApplication app;
public static AnddroidApplication getInstance() {
if (app == null) {
app = new AnddroidApplication();
}
return app;
}
}
上面这种方式如果是单纯的Java工程可能没有问题,但是在Android里这样说大错特错的。因为Application是系统组件,系统组件实例是要由系统去创建的,如果我们这里直接创建一个,不过是简单的Java对象而已,不具备任何Context能力,也无法进行任何Context操作。标准的写法就本文的第一段示意代码那样。
3)Application单例模式的正确写法
Application类比较特殊,不能直接new Application,一旦你New 了,就是个全新的对象而不是当前的Application对象了。
Application的onCreate方法一定会走,所以正确的单例模式应该这样写:
public class MyApplication extends Application {
private static MyApplication myApplication = null;
public static MyApplication getApplication() {
return myApplication;
}
@Override
public void onCreate() {
super.onCreate();
myApplication = this;
}
}