前言
上一篇文章記錄了組件化開發中的項目部署需要注意的地方,而本文旨在實現模塊之間的交互,比如頁面的跳轉,數據的傳遞等等,而在集成化模式下,各個子模塊都是library,到底該如何實現呢?首先我們要知道傳統的組件間的通信方式,以及其適用場景和優缺點。
組件間通信的傳統方式
- EventBus:不同的消息需要定義不同的EventBean(一對一),導致EventBean會非常多,而且一對多就會混亂、難以維護
- 反射:反射技術可以實現,維護成本高且容易出現高版本@hide限制
- 隱式意圖:維護成本還好,只是比較麻煩,需要維護Manifest中action
- BroadcastReceiver:需要動態註冊(7.0之後),需求方發送廣播
- 類加載:需要準確的全類名路徑,維護成本高且容易出現人爲失誤(包名路徑容易弄錯)
類加載技術交互實現
在personal模塊要跳轉到order模塊的Order_MainActivity,類加載技術實現主要邏輯如下:
// 類加載跳轉,可以成功,維護成本較高且容易出現人爲失誤
// 需要準確的全類名路徑
try{
Class targetClass = Class.forName("xpf.moudlar.deploy.order.Order_MainActivity");
Intent intent = new Intent(this, targetClass);
intent.putExtra("params","xpf");
startActivity(intnet);
}catch(ClassNotFoundException e) {
e.printStackTrace()
}
全局Map記錄信息實現
定義PathBean對象
- path屬性:跳轉目標字符串縮寫
- clazz屬性:跳轉目標Class對象
- 保存到common公共基礎庫,所有子模塊都可以調用
/**
* 路徑對象(公共基礎庫中,所有子模塊都可以調用)
* path:"order/Order_MainActivity"
* clazz: Order_MainActivity.class
*/
public class PathBean {
private String path;
private Class clazz;
public PathBean(String path, Class clazz) {
this.path = path;
this.clazz = clazz;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public Class getClazz() {
return clazz;
}
public void setClazz(Class clazz) {
this.clazz = clazz;
}
}
將需要跳轉的目標PathBean放在common公共基礎模塊的全局Map中,對外提供管理類,主要包含兩個方法,一個將對應模塊的Activity路徑信息分組保存到全局Map中。另一個方法就是根據組名和路徑信息獲取目標類的類對象,實現跳轉。
* 全局路徑記錄器(根據子模塊分組)
*/
public class RecordPathManager {
// key:組名"order" value: order子模塊下的所有Activity路徑信息
private static Map<String, List<PathBean>> groupMap = new HashMap<>();
/**
* 將路徑信息加入全局Map
*
* @param groupName 組名,如:"personal"
* @param pathName 路徑名,如:"Personal_MainActivity"
* @param clazz 類對象,如:Personal_MainActivity.class
*/
public static void joinGroup(String groupName, String pathName, Class<?> clazz) {
List<PathBean> list = groupMap.get(groupName);
if (list == null) {
list = new ArrayList<>();
list.add(new PathBean(pathName, clazz));
groupMap.put(groupName, list);
} else {
for (PathBean pathBean : list) {
if (!pathName.equals(pathBean.getPath())) {
list.add(new PathBean(pathName, clazz));
groupMap.put(groupName, list);
}
}
}
}
/**
* 根據組名和路徑名獲取類對象,達到跳轉目的
* @param groupName
* @param pathName
* @return
*/
public static Class<?> getTargetClass(String groupName, String pathName) {
List<PathBean> list = groupMap.get(groupName);
if (list == null) return null;
for (PathBean pathBean : list) {
// 比較路徑名時忽略大小寫
if (pathName.equalsIgnoreCase(pathBean.getPath())) {
return pathBean.getClazz();
}
}
return null;
}
}
試想一下,如果跳轉的時候,找不到類對象(比如Order_MainActivity.class), 就無法跳轉,也就是說在跳轉之前,要先將對應模塊的所有Activity路徑信息保存起來,可以在主模塊app的application裏面執行保存的操作,這樣所有的子模塊就都可以獲取到需要跳轉的目標PathBean進行跳轉了,避免了找不到對應目標信息的問題。
public class AppApplication extends BaseApplication {
@Override
public void onCreate() {
super.onCreate();
RecordPathManager.joinGroup("app", "MainActivity", MainActivity.class);
RecordPathManager.joinGroup("order", "Order_MainActivity", Order_MainActivity.class);
RecordPathManager.joinGroup("personal", "Personal_MainActivity", Personal_MainActivity.class);
}
}
在集成模式下,order和personal之間是相互沒有依賴關係的,通過RecordPathManager的getTargetClass方法獲取跳轉目標Activity的類對象,進行跳轉。下面僅舉例在order模塊,跳轉至app模塊的MainActivity和personal模塊的Personal_MainActivity,在personal等其它子模塊跳轉邏輯一樣。
public class Order_MainActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.order_activity_main);
Log.d(Cons.TAG, "common/Order_MainActivity");
}
// 跳轉至app模塊的MainActivity
public void jumpApp(View view) {
// 全局Map記錄路徑信息方式實現跳轉
Class<?> targetClass = RecordPathManager.getTargetClass("app", "MainActivity");
if (targetClass == null) {
Log.d(Cons.TAG, "獲取targetClass爲空");
}
Intent intent = new Intent(this, targetClass);
intent.putExtra("name", "xpf");
startActivity(intent);
}
// 跳轉至personal模塊的Personal_MainActivity
public void jumpPersonal(View view) {
// 全局Map記錄路徑信息方式實現跳轉
Class<?> targetClass = RecordPathManager.getTargetClass("personal", "Personal_MainActivity");
if (targetClass == null) {
Log.d(Cons.TAG, "獲取targetClass爲空");
}
Intent intent = new Intent(this, targetClass);
intent.putExtra("name", "xpf");
startActivity(intent);
}
}
大致思路如下圖:
總結
本文主要介紹了模塊之間交互的兩種方式,對於類加載實現方式,需要準確的全類名路徑。可以成功,維護成本較高且容易出現人爲失誤。而對於全局Map保存路徑和類對象信息實現方式,如果各個子模塊Activity較多比如200多個,也就是說在app模塊的application中對於保存信息的操作,要執行200次,這很不優雅,也不符合實際開發場景,能不能像個辦法生成一個類專門來處理application中對於的保存操作呢?答案是肯定的,我們可以通過apt生成一個類來專門處理這個任務,欲知詳情,且聽下回分解。
對於全局Map保存路徑和類對象信息實現方式,如果各個子模塊Activity較多比如200多個,也就是說在app模塊的application中對於保存信息的操作,要執行200次,這很不優雅,也不符合實際開發場景,能不能像個辦法生成一個類專門來處理application中對於的保存操作呢?答案是肯定的,我們可以通過apt生成一個類來專門處理這個任務,欲知詳情,且聽下回分解。