android 应用动态加载机制2--资源加载机制和Activity生命周期管理

我们知道,activity的工作主要是由ContextImpl来完成的, 它在activity中是一个叫做mBase的成员变量。注意到Context中有如下两个抽象方法,看起来是和资源有关的,实际上context就是通过它们来获取资源的,这两个抽象方法的真正实现在ContextImpl中。也即是说,只要我们自己实现这两个方法,就可以解决资源问题了。

/** Return an AssetManager instance for your application’s package. */

public abstract AssetManager getAssets();

/** Return a Resources instance for your application’s package. */

public abstract Resources getResources();

下面看一下如何实现这两个方法

首先要加载apk中的资源:

[java]  view plain  copy

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. protected void loadResources() {

  2. try {

  3. AssetManager assetManager = AssetManager.class.newInstance();

  4. Method addAssetPath = assetManager.getClass().getMethod(“addAssetPath”, String.class);

  5. addAssetPath.invoke(assetManager, mDexPath);

  6. mAssetManager = assetManager;

  7. } catch (Exception e) {

  8. e.printStackTrace();

  9. }

  10. Resources superRes = super.getResources();

  11. mResources = new Resources(mAssetManager, superRes.getDisplayMetrics(),

  12. superRes.getConfiguration());

  13. mTheme = mResources.newTheme();

  14. mTheme.setTo(super.getTheme());

  15. }

说明:加载的方法是通过反射,通过调用AssetManager中的addAssetPath方法,我们可以将一个apk中的资源加载到Resources中,由于addAssetPath是隐藏api我们无法直接调用,所以只能通过反射,下面是它的声明,通过注释我们可以看出,传递的路径可以是zip文件也可以是一个资源目录,而apk就是一个zip,所以直接将apk的路径传给它,资源就加载到AssetManager中了,然后再通过AssetManager来创建一个新的Resources对象,这个对象就是我们可以使用的apk中的资源了,这样我们的问题就解决了。

[java]  view plain  copy

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. /**

  2. * Add an additional set of assets to the asset manager.  This can be

  3. * either a directory or ZIP file.  Not for use by applications.  Returns

  4. * the cookie of the added asset, or 0 on failure.

  5. * {@hide}

  6. */

  7. public final int addAssetPath(String path) {

  8. int res = addAssetPathNative(path);

  9. return res;

  10. }

其次是要实现那两个抽象方法

[java]  view plain  copy

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. @Override

  2. public AssetManager getAssets() {

  3. return mAssetManager == null ? super.getAssets() : mAssetManager;

  4. }

  5. @Override

  6. public Resources getResources() {

  7. return mResources == null ? super.getResources() : mResources;

  8. }

okay,问题搞定。这样一来,在apk中就可以通过R来访问资源了。

activity生命周期的管理


这是本文开头提到的另一个需要解决的难题。为什么会有这个问题,其实很好理解,apk被宿主程序调起以后,apk中的activity其实就是一个普通的对象,不具有activity的性质,因为系统启动activity是要做很多初始化工作的,而我们在应用层通过反射去启动activity是很难完成系统所做的初始化工作的,所以activity的大部分特性都无法使用包括activity的生命周期管理,这就需要我们自己去管理。谈到activity生命周期,其实就是那几个常见的方法:onCreate、onStart、onResume、onPause等,由于apk中的activity不是真正意义上的activity(没有在宿主程序中注册且没有完全初始化),所以这几个生命周期的方法系统就不会去自动调用了。针对此类问题,采用Fragment是一个不错的方法,Fragment从3.0引入,通过support-v4包,可以兼容3.0以下的android版本。Fragment既有类似于Activity的生命周期,又有类似于View的界面,将Fragment加入到Activity中,activity会自动管理Fragment的生命周期,通过第一篇文章我们知道,apk中的activity是通过宿主程序中的代理activity启动的,将Fragment加入到代理activity内部,其生命周期将完全由代理activity来管理,但是采用这种方法,就要求apk尽量采用Fragment来实现,还有就是在做页面跳转的时候有点麻烦,当然关于Fragment相关的内容我将在后面再做研究,本文不采用Fragment而是通过反射去手动管理activity的生命周期。

我们要在代理activity中去反射apk中activity的所有生命周期的方法,然后将activity的生命周期和代理activity的生命周期进行同步。首先,反射activity生命周期的所有方法,还反射了onActivityResult这个方法,尽管它不是典型的生命周期方法,但是它很有用。

[java]  view plain  copy

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. protected void instantiateLifecircleMethods(Class<?> localClass) {

  2. String[] methodNames = new String[] {

  3. “onRestart”,

  4. “onStart”,

  5. “onResume”,

  6. “onPause”,

  7. “onStop”,

  8. “onDestory”

  9. };

  10. for (String methodName : methodNames) {

  11. Method method = null;

  12. try {

  13. method = localClass.getDeclaredMethod(methodName, new Class[] { });

  14. method.setAccessible(true);

  15. } catch (NoSuchMethodException e) {

  16. e.printStackTrace();

  17. }

  18. mActivityLifecircleMethods.put(methodName, method);

  19. }

  20. Method onCreate = null;

  21. try {

  22. onCreate = localClass.getDeclaredMethod(“onCreate”, new Class[] { Bundle.class });

  23. onCreate.setAccessible(true);

  24. } catch (NoSuchMethodException e) {

  25. e.printStackTrace();

  26. }

  27. mActivityLifecircleMethods.put(“onCreate”, onCreate);

  28. Method onActivityResult = null;

  29. try {

  30. onActivityResult = localClass.getDeclaredMethod(“onActivityResult”,

  31. new Class[] { int.class, int.class, Intent.class });

  32. onActivityResult.setAccessible(true);

  33. } catch (NoSuchMethodException e) {

  34. e.printStackTrace();

  35. }

  36. mActivityLifecircleMethods.put(“onActivityResult”, onActivityResult);

  37. }

其次,同步生命周期,主要看一下onResume和onPause,其他方法是类似的。看如下代码,很好理解,就是当系统调用代理activity生命周期方法的时候,就通过反射去显式调用apk中activity的对应方法。

[java]  view plain  copy

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. @Override

  2. protected void onResume() {

  3. super.onResume();

学习福利

【Android 详细知识点思维脑图(技能树)】

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。

这里附上上述的面试题相关的几十套字节跳动,京东,小米,腾讯、头条、阿里、美团等公司19年的面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

由于篇幅有限,这里以图片的形式给大家展示一小部分。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
花了不少精力),包含知识脉络 + 诸多细节。

由于篇幅有限,这里以图片的形式给大家展示一小部分。

[外链图片转存中…(img-QnUJTqiS-1714684003586)]

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值