Context之间的关系
可以看到,Context的具体实现是在ContextIml和ContextWrapper之中,而经过阅读源码发现,Resource的构造主要是在ContextIml中实现的,接下来的部分分析源码的调用流程。
context.getResource的调用原理:
该部分主要涉及到的是源码的阅读,此处贴一张UML时序图,有兴趣的可以自行阅读:
Context的用法:
- 获取屏幕方向int类型,1:portrait,2:landscape
context.getResources().getConfiguration().orientation;
- 资源文件名为index.html, 不需要带后缀.htm
InputStream fs =this.getResources().openRawResource(R.raw.index.htm);
InputStreamReader read = new InputStreamReader (fs,"utf-8");
BufferedReader in = new BufferedReader(read);
- 读取res/drawable目录下的png或者bmp
- 得到Resources对象
Resources r = this.getContext().getResources();
- 以数据流的方式读取资源
Inputstream is = r.openRawResource(R.drawable.mm_image);
BitmapDrawable bmpDraw = new BitmapDrawable(is);
Bitmap bmp = bmpDraw.getBitmap();
- 获取屏幕密度
float density = getResources().getDisplayMetrics().density;
- 获取dimens资源定义的像素数
Context.getResources().getDimensionPixelSize();
- 获取颜色资源
Context.getResources().getColor(R.color.colorId);
- 获取字符串资源
Context.getResources().getString(R.string.stringId);
- 获取字符串数组:
String[] roles = context.getResources().getStringArray(R.array.array_role_values);
完整的Resource对用流程(从应用启动开始)
- 在主页点击App,此时是运行在Launcher进程,通过ActivityManagerServiceBinder IPC的形式向system_server进程发起startActivity的请求
- system_server进程接收到请求后,通过Process.start方法向zygote进程发送创建进程的请求
zygote进程fork出新的子进程,即App进程 - 进入ActivityThread.main方法中,这时运行在App进程中,通过ActivityManagerServiceBinder IPC的形式向system_server进程发起attachApplication请求
- server给Binder线程发送Secheduled launcher,binder给Activity.thread发送LaunchActivity
- Activity.thread执行
- 创建contex:ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
- ContextImpl初始化时获取Resources对象: Resources resources = packageInfo.getResources(mainThread); (LoadedApk类型)
- createResourcesImpl中调用了createAssetManager,绑定了addAssetPath
接下来就和上文所述的Resource获取相同,不再多做赘述。
Q&A
一个应用中Context的数量?
Activity数量+Service数量+Application数量(通常为1,一个进程中只有一个Application)
扩展和引申
- java类加载机制
2.H5的加载流程, React Native、Weex呢