前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Android 插件化】“ 插桩式 “ 插件化框架 ( 注入上下文的使用 )

【Android 插件化】“ 插桩式 “ 插件化框架 ( 注入上下文的使用 )

作者头像
韩曙亮
发布2023-03-29 13:30:58
2680
发布2023-03-29 13:30:58
举报
文章被收录于专栏:韩曙亮的移动开发专栏

Android 插件化系列文章目录

【Android 插件化】插件化简介 ( 组件化与插件化 )

【Android 插件化】插件化原理 ( JVM 内存数据 | 类加载流程 )

【Android 插件化】插件化原理 ( 类加载器 )

【Android 插件化】“ 插桩式 “ 插件化框架 ( 原理与实现思路 )

【Android 插件化】“ 插桩式 “ 插件化框架 ( 类加载器创建 | 资源加载 )

【Android 插件化】“ 插桩式 “ 插件化框架 ( 注入上下文的使用 )

【Android 插件化】“ 插桩式 “ 插件化框架 ( 获取插件入口 Activity 组件 | 加载插件 Resources 资源 )

【Android 插件化】“ 插桩式 “ 插件化框架 ( 运行应用 | 代码整理 )


文章目录


前言

参考 【Android 插件化】“ 插桩式 “ 插件化框架 ( 原理与实现思路 ) 中给出的实现思路 , 逐步实现 “ 插桩式 “ 插件化框架 ;

【Android 插件化】“ 插桩式 “ 插件化框架 ( 类加载器创建 | 资源加载 ) 博客中 , 开发了 DexClassLoader 类加载器加载插件包 , 并使用 AssetManager 加载插件包资源的模块 ;

【Android 插件化】“ 插桩式 “ 插件化框架 ( 代理 Activity 组件开发 ) 博客中开发开发本地的 Activity 桩 , 即空壳 Activity , 用于持有插件界面组件 , 并在生命周期中回调插件界面 Activity 组件的对应生命周期方法 ;

本博客中开发插件包中的 Activity , 并进行插件化调用 ; 所有的插件包中的 Activity 都要继承 BaseActivity , 插件 Activity 中的相关功能都要使用 BaseActivity 中被注入的上下文进行代理操作 ;


一、BaseActivity 注入上下文的使用

在上一篇博客 【Android 插件化】“ 插桩式 “ 插件化框架 ( 代理 Activity 组件开发 ) 中实现了 BaseActivity , 这是所有 " 插件 " 模块中 Activity 类的基类 , 其中的 private Activity proxyActivity 成员的作用是充当 插件 Activity 中的上下文 ;

代码语言:javascript
复制
public class BaseActivity extends AppCompatActivity implements PluginActivityInterface {
    /**
     * 注入的 Activity , 代理该 Activity 类作为上下文
     */
    private Activity proxyActivity;
}

插件包中的 Activity 没有上下文对象 , 如果在插件包中的 PluginActivity 中调用与上下文相关的方法 , 如 findViewById 查找组件 , 肯定是无法实现的 , 必须修改 BaseActivity 中与上下文相关的方法 ;

setContentView 中需要调用 supersetContentView 方法 , 这里的上下文是无效的 , 也无法成功加载布局文件 , 因此必须调用 private Activity proxyActivity 成员的 setContentView 方法加载布局文件 ;

代码语言:javascript
复制
// 在 BaseActivity 中调用如下方法是不生效的 
@Override
public void setContentView(int layoutResID) {
    super.setContentView(layoutResID);
}

需要进行如下修改 , 使用注入的上下文设置布局文件 , 这个注入的上下文就是代理 Activity , ProxyActivity ;

代码语言:javascript
复制
@Override
public void setContentView(int layoutResID) {
    // 调用代理 Activity 中的 setContentView 方法
    if (proxyActivity == null) {
        proxyActivity.setContentView(layoutResID);
    }else{
        super.setContentView(layoutResID);
    }
}

这里说明一下

代码语言:javascript
复制
if (proxyActivity == null) {
    proxyActivity.setContentView(layoutResID);
}else{
    super.setContentView(layoutResID);
}

分支的作用 , 在正式发布以后走的是 if (proxyActivity == null) 分支 , 但是在开发阶段 , 并没有注入 Activity , 开发者在组件化调试的时候使用的是 else 分支 , 这里特别注意 , 一定要实现 else 分支 , 否则开发时无法调试 ;

同理 public void setContentView(View view) 方法也需要如下修改 , 将

代码语言:javascript
复制
@Override
public void setContentView(View view) {
    super.setContentView(view);
}

修改为 :

代码语言:javascript
复制
@Override
public void setContentView(View view) {
    // 调用代理 Activity 中的 setContentView 方法
    if (proxyActivity == null) {
        proxyActivity.setContentView(view);
    }else{
        super.setContentView(view);
    }
}

public <T extends View> T findViewById(int id) 进行如下修改 , 将

代码语言:javascript
复制
@Override
public <T extends View> T findViewById(int id) {
    return super.findViewById(id);
}

修改为 :

代码语言:javascript
复制
@Override
public <T extends View> T findViewById(int id) {
    if (proxyActivity == null) {
        return proxyActivity.findViewById(id);
    }else{
        return super.findViewById(id);
    }
}

public void startActivity(Intent intent) 方法由

代码语言:javascript
复制
@Override
public void startActivity(Intent intent) {
    super.startActivity(intent);
}

修改为 : 注意需要将类名放入 intent , 这个类名就是真正的调用界面跳转的类的类名 ;

代码语言:javascript
复制
@Override
public void startActivity(Intent intent) {
    if (proxyActivity == null) {
        intent.putExtra("className", intent.getComponent().getClassName());
        proxyActivity.startActivity(intent);
    }else{
        super.startActivity(intent);
    }
}

二、BaseActivity 完整代码

BaseActivity 完整代码 :

代码语言:javascript
复制
package com.example.plugin_core;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

/**
 * " 插件 " 模块中的 Activity 类都继承该类
 * 具体的 Activity 业务类的父类
 */
public class BaseActivity extends AppCompatActivity implements PluginActivityInterface {

    /**
     * 注入的 Activity , 代理该 Activity 类作为上下文
     */
    private Activity proxyActivity;

    /**
     * 注入代理 Activity
     * 在 ProxyActivity 中将代理 Activity 组件注入进来
     * @param proxyActivity
     */
    @Override
    public void attach(Activity proxyActivity) {
        this.proxyActivity = proxyActivity;
    }

    @Override
    public void setContentView(int layoutResID) {
        // 调用代理 Activity 中的 setContentView 方法
        if (proxyActivity == null) {
            proxyActivity.setContentView(layoutResID);
        }else{
            super.setContentView(layoutResID);
        }
    }

    @Override
    public void setContentView(View view) {
        // 调用代理 Activity 中的 setContentView 方法
        if (proxyActivity == null) {
            proxyActivity.setContentView(view);
        }else{
            super.setContentView(view);
        }
    }

    @Override
    public <T extends View> T findViewById(int id) {
        if (proxyActivity == null) {
            return proxyActivity.findViewById(id);
        }else{
            return super.findViewById(id);
        }
    }

    @Override
    public void startActivity(Intent intent) {
        if (proxyActivity == null) {
            intent.putExtra("className", intent.getComponent().getClassName());
            proxyActivity.startActivity(intent);
        }else{
            super.startActivity(intent);
        }
    }

    @SuppressLint("MissingSuperCall")
    @Override
    public void onCreate(Bundle savedInstanceState) {

    }

    @SuppressLint("MissingSuperCall")
    @Override
    public void onStart() {

    }

    @SuppressLint("MissingSuperCall")
    @Override
    public void onResume() {

    }

    @SuppressLint("MissingSuperCall")
    @Override
    public void onPause() {

    }

    @SuppressLint("MissingSuperCall")
    @Override
    public void onStop() {

    }

    @SuppressLint("MissingSuperCall")
    @Override
    public void onDestroy() {

    }

    @SuppressLint("MissingSuperCall")
    @Override
    public void onSaveInstanceState(Bundle outState) {

    }
}

三、博客资源

博客资源 :


总结

" 插件 " 模块中的所有 Activity 都要继承 BaseActivity , " 宿主 " 模块运行时 , 为 BaseActivity 中注入了上下文 , 所有涉及上下文的操作 , 如 setContentView , findViewById , startActivity 等方法 , 都需要借助注入的上下文来完成 , 使用插件 Activity 无法完成上述操作 ;

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-06-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Android 插件化系列文章目录
    • 文章目录
    • 前言
    • 一、BaseActivity 注入上下文的使用
    • 二、BaseActivity 完整代码
    • 三、博客资源
    • 总结
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档