【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*/@Overridepublic void attach(Activity proxyActivity) {this.proxyActivity = proxyActivity;}@Overridepublic void setContentView(int layoutResID) {// 調用代理 Activity 中的 setContentView 方法if (proxyActivity == null) {proxyActivity.setContentView(layoutResID);}else{super.setContentView(layoutResID);}}@Overridepublic void setContentView(View view) {// 調用代理 Activity 中的 setContentView 方法if (proxyActivity == null) {proxyActivity.setContentView(view);}else{super.setContentView(view);}}@Overridepublic <T extends View> T findViewById(int id) {if (proxyActivity == null) {return proxyActivity.findViewById(id);}else{return super.findViewById(id);}}@Overridepublic void startActivity(Intent intent) {if (proxyActivity == null) {intent.putExtra("className", intent.getComponent().getClassName());proxyActivity.startActivity(intent);}else{super.startActivity(intent);}}@SuppressLint("MissingSuperCall")@Overridepublic void onCreate(Bundle savedInstanceState) {}@SuppressLint("MissingSuperCall")@Overridepublic void onStart() {}@SuppressLint("MissingSuperCall")@Overridepublic void onResume() {}@SuppressLint("MissingSuperCall")@Overridepublic void onPause() {}@SuppressLint("MissingSuperCall")@Overridepublic void onStop() {}@SuppressLint("MissingSuperCall")@Overridepublic void onDestroy() {}@SuppressLint("MissingSuperCall")@Overridepublic void onSaveInstanceState(Bundle outState) {} }三、博客資源
博客資源 :
- GitHub : https://github.com/han1202012/Plugin
總結
" 插件 " 模塊中的所有 Activity 都要繼承 BaseActivity , " 宿主 " 模塊運行時 , 為 BaseActivity 中注入了上下文 , 所有涉及上下文的操作 , 如 setContentView , findViewById , startActivity 等方法 , 都需要借助注入的上下文來完成 , 使用插件 Activity 無法完成上述操作 ;
總結
以上是生活随笔為你收集整理的【Android 插件化】“ 插桩式 “ 插件化框架 ( 注入上下文的使用 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【商务智能】商务智能 ( 概念 | 组成
- 下一篇: 【Android 安装包优化】APK 打