架构师学习--插件化之占位式(插桩式)

什么是插件化?插件化开发是将整个app拆分成很多模块,这些模块包括一个宿主和多个插件,每个模块都是一个apk。插件apk是不需要安装的,运行在手机上的是宿主apk,当需要插件内容的时候,就需要通过宿主apk先加载插件,然后才能操作插件,也就是说插件是没有独立运行环境的,必须依赖宿主的环境
学习插件化,需要了解宿主、插件和标准的关系

  1. 宿主:运行在手机上的apk
  2. 插件:服务器上下载的apk包,没有经过安装
  3. 标准:指插件应该遵循宿主提供的接口协议

下面就以启动插件activity为例,开始撸代码环节

一、创建宿主标准

创建library库,另外这些标准一般都是宿主中的方法,比如生命周期方法等,另外需要将宿主的上下文环境传递给插件activity,所以定义接口PluginActivityInterface,代码如下:
在这里插入图片描述

二、创建宿主插件包

记住一点插件是一个apk,所以创建的应该是module。

1、BaseActivity

创建基类,实现了宿主的接口标准,并拿到宿主的上下文环境
在这里插入图片描述

2、MainActivity

在插件中创建一个启动的activity,命名MainActivity,继承BaseActivity。并在相对应的xml布局中添加了几个按钮
在这里插入图片描述
这里的findViewById不能是系统的,而应该是宿主的,因为插件是没有上下文环境的,使用默认系统的会抛出异常。所以这里会调用父类BaseActivity的该方法,父类BaseActivity的这部分代码如下:
在这里插入图片描述
最终会调用宿主mActivity的该方法,startActivity也是同样的道理。这里的mActivity其实就是代理Activity。

三、创建代理activity

为什么要创建代理activity?我们都知道activity的跳转就是一个压栈的过程,创建代理activity其实就是为插件activity模拟这一过程,这样当我们点击返回键的时候才能从插件回到宿主activity中。代码如下:

/**
 * <pre>
 *     author  : QB
 *     time    : 2019/8/6
 *     version : v1.0.0
 *     desc    : 必须继承 Activity 继承AppcompatActivity会出错
 * </pre>
 */
public class ProxyActivity extends Activity {
    @Override
    public Resources getResources() {
        return PluginManager.getInstance(this).getPluginResource();
    }

    @Override
    public ClassLoader getClassLoader() {
        return PluginManager.getInstance(this).getClassLoader();
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //通过classLoader加载插件的class文件
        String className = getIntent().getStringExtra("className");

        Log.e("类名-----", className);

        try {

            //加载插件activity类信息
            Class<?> aClass = getClassLoader().loadClass(className);

            Constructor<?> constructor = aClass.getConstructor();

            Object obj = constructor.newInstance();

            //实例化插件activity类
            PluginActivityInterface pluginInterface = (PluginActivityInterface) obj;

            //初始化插件上下文
            pluginInterface.initApp(this);

            Bundle bundle = new Bundle();
            bundle.putString("className", "宿主跳转到插件");

            //执行插件activity的onCreate()方法
            pluginInterface.onCreate(bundle);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 将插件中启动页面压入栈中
     */
    public void startActivity(Intent intent) {
        String className = intent.getStringExtra("className");
        Intent intentNew = new Intent(this, ProxyActivity.class);
        intentNew.putExtra("className", className);
        super.startActivity(intentNew);
    }

    
}

上面重写了两个方法getClassLoader()和getResources()。这两个方法返回的是对应插件app的类加载器和资源,,只有拿到类加载器才能通过反射拿到要操作的插件activity对象;只有拿到资源信息才能够加载layout布局(否则之前调用mActivity.findViewById()会找不到我们的控件)。下面就看一下插件的安装过程,就是将这两个东东进行初始化。

四、安装插件

插件apk,打包成功后,放在data/sdcard目录下,获取插件apk的路径
在这里插入图片描述

1、获取插件包的类加载器

在这里插入图片描述

2、获取插件包的资源

在这里插入图片描述

3、提供方法供外部调用

在这里插入图片描述

五、跳转到插件activity

这里我们需要拿到插件apk中清单文件注册的第一个activity,也就是启动activity。
在这里插入图片描述
这样就拿到了插件activity的类名。跳转到代理activity的时候将类名称信息保存到intent中携带过去,这样才能通过插件的classLoader将类加载出来。

最后别忘记加访问sdcard权限哦!!!!

总结:

1:插件中为什么不能使用this
答:因为插件是没有安装手机上安装的,是无法拥有组件环境的
2:插件中为什么要是用代理的activity
答:由于插件中的Activity,并不是一个能够运行的组件,所以需要代理的Activity去代替 插件中的Activity (例如:Activity任务进栈)。

下一节将讲述如何去处理插件中静态广播的注册?

完整代码:

插件化代码传送门

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值