插件化框架解读之四大组件调用原理-Activity

LogRelease.w(PLUGIN_TAG, “use f.a, c=” + container);
}
return ForwardActivity.class;
}
plugin = state.plugin;
activity = state.activity;

Plugin p = mPluginMgr.loadAppPlugin(plugin);
if (p == null) {
return null;
}
ClassLoader cl = p.getClassLoader();
if (LOG) {
Class<?> c = null;
try {
c = cl.loadClass(activity);
} catch (Throwable e) {
if (LOGR) {
LogRelease.e(PLUGIN_TAG, e.getMessage(), e);
}
}
return c;
}

这样我们插件目标Activity就恢复成功,目标Activity内部逻辑就能正常执行啦。
总结:
开启插件Activity的大致流程为:
插件Activity -> Replugin.startActivity -> 解析出插件Activity对应的pluginName -> 挑选坑位Activity替换 ->调用系统startActivity方法 -> AMS回调执行坑位Activity类加载 ->加载并初始化目标插件资源、上下文、类加载器(首次) ->Hook掉ClassLoader的类加载中恢复为插件Activity -> 插件Activity启动,并拥有完整生命周期。

二、插件内部startActivity流程

插件中startActiviy有两种场景:调用自己插件本身的Activity或者调用宿主的Activity。显然光凭插件自己是无法成功开启的。因为插件的Manifest根本就没有被AMS识别到呀,必须还是要用统一的Replugin.startActivity接口去按照上述分析的流程重走一遍才行的啊。
在《Replugin插件化技术解读之目录结构解读》一文中,我们了解到其实插件在动态编译过程中会在字节码层做适量修改,如插件的所有Activity都会被继承replugin-plugin-lib中的PluginActivity这样一个基类。所以我们插件内部其实Activity内部最后执行startActivity都会先走PluginActivity的此方法;
PluginActivity.java

static void initLocked(final ClassLoader classLoader) {

final String factory2 = “com.qihoo360.i.Factory2”;
final String factory = “com.qihoo360.i.Factory”;

// 初始化Factory2相关方法
createActivityContext = new MethodInvoker(classLoader, factory2, “createActivityContext”, new Class<?>[]{Activity.class, Context.class}); handleActivityCreateBefore = new MethodInvoker(classLoader, factory2, "handleActivityCreateBefore", new Class<?>[]{Activity.class, Bundle.class});
handleActivityCreate = new MethodInvoker(classLoader, factory2, “handleActivityCreate”, new Class<?>[]{Activity.class, Bundle.class}); handleActivityDestroy = new MethodInvoker(classLoader, factory2, "handleActivityDestroy", new Class<?>[]{Activity.class});
handleRestoreInstanceState = new MethodInvoker(classLoader, factory2, “handleRestoreInstanceState”, new Class<?>[]{Activity.class, Bundle.class}); startActivity = new MethodInvoker(classLoader, factory2, "startActivity", new Class<?>[]{Activity.class, Intent.class});
startActivityForResult = new MethodInvoker(classLoader, factory2, “startActivityForResult”, new Class<?>[]{Activity.class, Intent.class, int.class, Bundle.class});

// 初始化Factory相关方法
loadPluginActivity = new MethodInvoker(classLoader, factory, “loadPluginActivity”, new Class<?>[]{Intent.class, String.class, String.class, int.class});

显然,反射的是Factory2中的startActivity方法,而Factory.startActivity其实就是调用的PmInternalmpl.startActivity方法,显然这个跟上面宿主启动插件Activity对上啦。

那么RepluginInternal.initLocked方法是什么时候走的呢?容易看到是在RepluginFramework.init中调用,而RepluginFramework.init初始化时在Entry的create方法中,这里是不是很熟悉啦。没错,在《Replugin插件化技术解读之框架初始化、插件安装与加载(二)》一文中我们知道在加载插件的时候会通过回调执行插件的Entry的create方法初始化插件,显然这里这条线又连上啦。

这样插件内部启动startActivity说白了就是通过反射调用宿主Factory2中startActivity方法去重走了遍上述分析的标准启动插件Activity流程。注意,这里其实仅仅是通过插件Activity继承PluginActivity重写了Activity内部StartActivity方法,改变了Activity内startActivity方法启动步骤。

我们显然还要修改Context上下文对应的startActivity方法才能保证这里调用的时候也会走到我们设定好的宿主startActivityq启动流程,

那么插件内部其他startActivity的地方都要进行这样的调整才行,这个就大家自己跟下就能明白了,原理差不多。

public abstract class PluginActivity extends Activity {

@Override
protected void attachBaseContext(Context newBase) {
newBase = RePluginInternal.createActivityContext(this, newBase);
super.attachBaseContext(newBase);
}

PluginActivity的attachBaseContext方法中我们会使用RepluginInternal.createActivityContext方法,通过反射,最终吊起来PmInternalImpl.createActivityContext方法。创建对应插件的PluginContext对象,PluginContext前文已经介绍,然后用这个PluginContext替换掉插件内部的上下文BaseContext,其实也就是Activity继承的ContextWrapper类的Context mBase对象。跟踪Android源码很容易发现,ContextWrapper内部封装了startActivity startService等方法,所以这里我们要将这个Context替换掉。那么PluginContext内部又做了什么呢?显然它也重写了startActivity方法。

@Override
public void startActivity(Intent intent) {
if (mContextInjector != null) {
mContextInjector.startActivityBefore(intent);
}

super.startActivity(intent);

if (mContextInjector != null) {
mContextInjector.startActivityAfter(intent);
}
}

这里 super.startActivity其实就是对应宿主上下文了,直接走宿主startActivity流程。
其他还有在PluginApplicationClient为插件创建的Application对象,在PluginApplicationClient.callAttachBaseContext方法中使用反射调用了Application.attachf方法,用PluginContext对象替换了原来的Context,这个就各位看官自己去梳理了哈。

原文链接https://blog.csdn.net/hellogmm/article/details/79058135
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

最后

文章不易,如果大家喜欢这篇文章,或者对你有帮助希望大家多多点赞转发关注哦。文章会持续更新的。绝对干货!!!

  • Android进阶学习全套手册
    关于实战,我想每一个做开发的都有话要说,对于小白而言,缺乏实战经验是通病,那么除了在实际工作过程当中,我们如何去更了解实战方面的内容呢?实际上,我们很有必要去看一些实战相关的电子书。目前,我手头上整理到的电子书还算比较全面,HTTP、自定义view、c++、MVP、Android源码设计模式、Android开发艺术探索、Java并发编程的艺术、Android基于Glide的二次封装、Android内存优化——常见内存泄露及优化方案、.Java编程思想 (第4版)等高级技术都囊括其中。

  • Android高级架构师进阶知识体系图
    关于视频这块,我也是自己搜集了一些,都按照Android学习路线做了一个分类。按照Android学习路线一共有八个模块,其中视频都有对应,就是为了帮助大家系统的学习。接下来看一下导图和对应系统视频吧!!!

  • Android对标阿里P7学习视频

  • BATJ大厂Android高频面试题
    这个题库内容是比较多的,除了一些流行的热门技术面试题,如Kotlin,数据库,Java虚拟机面试题,数组,Framework ,混合跨平台开发,等

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

ux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算**

  • 14
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值