【Android 插件化】“ 插桩式 “ 插件化框架 ( 注入上下文的使用 )
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 中的上下文 ;
public class BaseActivity extends AppCompatActivity implements PluginActivityInterface {
/**
* 注入的 Activity , 代理该 Activity 类作为上下文
*/
private Activity proxyActivity;
}
- 1
- 2
- 3
- 4
- 5
- 6
插件包中的 Activity 没有上下文对象 , 如果在插件包中的 PluginActivity 中调用与上下文相关的方法 , 如 findViewById
查找组件 , 肯定是无法实现的 , 必须修改 BaseActivity 中与上下文相关的方法 ;
setContentView
中需要调用 super
的 setContentView
方法 , 这里的上下文是无效的 , 也无法成功加载布局文件 , 因此必须调用 private Activity proxyActivity
成员的 setContentView
方法加载布局文件 ;
// 在 BaseActivity 中调用如下方法是不生效的
@Override
public void setContentView(int layoutResID) {
super.setContentView(layoutResID);
}
- 1
- 2
- 3
- 4
- 5
需要进行如下修改 , 使用注入的上下文设置布局文件 , 这个注入的上下文就是代理 Activity , ProxyActivity ;
@Override
public void setContentView(int layoutResID) {
// 调用代理 Activity 中的 setContentView 方法
if (proxyActivity == null) {
proxyActivity.setContentView(layoutResID);
}else{
super.setContentView(layoutResID);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
这里说明一下
if (proxyActivity == null) {
proxyActivity.setContentView(layoutResID);
}else{
super.setContentView(layoutResID);
}
- 1
- 2
- 3
- 4
- 5
分支的作用 , 在正式发布以后走的是 if (proxyActivity == null)
分支 , 但是在开发阶段 , 并没有注入 Activity , 开发者在组件化调试的时候使用的是 else
分支 , 这里特别注意 , 一定要实现 else 分支 , 否则开发时无法调试 ;
同理 public void setContentView(View view)
方法也需要如下修改 , 将
@Override
public void setContentView(View view) {
super.setContentView(view);
}
- 1
- 2
- 3
- 4
修改为 :
@Override
public void setContentView(View view) {
// 调用代理 Activity 中的 setContentView 方法
if (proxyActivity == null) {
proxyActivity.setContentView(view);
}else{
super.setContentView(view);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
public <T extends View> T findViewById(int id)
进行如下修改 , 将
@Override
public <T extends View> T findViewById(int id) {
return super.findViewById(id);
}
- 1
- 2
- 3
- 4
修改为 :
@Override
public <T extends View> T findViewById(int id) {
if (proxyActivity == null) {
return proxyActivity.findViewById(id);
}else{
return super.findViewById(id);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
public void startActivity(Intent intent)
方法由
@Override
public void startActivity(Intent intent) {
super.startActivity(intent);
}
- 1
- 2
- 3
- 4
修改为 : 注意需要将类名放入 intent , 这个类名就是真正的调用界面跳转的类的类名 ;
@Override
public void startActivity(Intent intent) {
if (proxyActivity == null) {
intent.putExtra("className", intent.getComponent().getClassName());
proxyActivity.startActivity(intent);
}else{
super.startActivity(intent);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
二、BaseActivity 完整代码
BaseActivity 完整代码 :
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) {
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
三、博客资源
博客资源 :
- GitHub : https://github.com/han1202012/Plugin
总结
" 插件 " 模块中的所有 Activity 都要继承 BaseActivity , " 宿主 " 模块运行时 , 为 BaseActivity 中注入了上下文 , 所有涉及上下文的操作 , 如 setContentView
, findViewById
, startActivity
等方法 , 都需要借助注入的上下文来完成 , 使用插件 Activity 无法完成上述操作 ;
文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。
原文链接:hanshuliang.blog.csdn.net/article/details/117573108
- 点赞
- 收藏
- 关注作者
评论(0)