0
点赞
收藏
分享

微信扫一扫

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

Android 插件化系列文章目录

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

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

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

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

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

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

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

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

文章目录

  • Android 插件化系列文章目录
  • 前言
  • 一、BaseActivity 注入上下文的使用
  • 二、BaseActivity 完整代码
  • 三、博客资源
  • 总结

前言

参考 【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;
}

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

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

// 在 BaseActivity 中调用如下方法是不生效的 
@Override
public void setContentView(int layoutResID) {
super.setContentView(layoutResID);
}

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

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

这里说明一下

if (proxyActivity == null) {
proxyActivity.setContentView(layoutResID);
}else{
super.setContentView(layoutResID);
}

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

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

@Override
public void setContentView(View view) {
super.setContentView(view);
}

修改为 :

@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) 进行如下修改 , 将

@Override
public <T extends View> T findViewById(int id) {
return super.findViewById(id);
}

修改为 :

@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) 方法由

@Override
public void startActivity(Intent intent) {
super.startActivity(intent);
}

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

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

二、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) {

}
}

三、博客资源

​博客资源 :​

  • ​GitHub :​ https://github.com/han1202012/Plugin

总结

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

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

举报

相关推荐

0 条评论