雖然說模塊通信、路由協議在Android已經不新鮮了,但是如果脫離了那些優秀的開源庫我們從零開始自己造一個庫,有時候重復造輪子會讓自己對所謂"車"的原理懂得更透徹。
直接上造完的輪子地址: https://github.com/Neacy/NeacyComponent
這個輪子有兩個大功能分別是模塊通信以及路由跳轉:
模塊通信
首先,統一聲明姿勢:
1
2
3
4
5
6
|
public interface IComponent { String getName(); void startComponent(ComponentParam param); } |
也就是說,在各自的維護的模塊內若想提供一個類供別的模塊調用那么需要實現這個 IComponent 類,這樣子可以根據面向對象的優勢統一管理,所以我們就有了接下來的這么一個個Component類,比如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
@NeacyComponent ( "app" ) public class AppComponent implements IComponent { @Override public String getName() { return "app" ; } @Override public void startComponent(ComponentParam param) { Log.w( "Jayuchou" , "==== Start AppComponent ====" ); if (param != null && param.getParam().containsKey( "callback" )) { ICallBack callBack = (ICallBack) param.getParam().get( "callback" ); Map<String, Object> results = new HashMap<>(); results.put( "result" , "我來自AppComponent" ); ComponentParam cp = new ComponentParam(results); callBack.onComponentBack(cp); } } } |
兩個地方比較重要:
- NeacyComponent 這個注釋,主要是為后面的gradle掃描使用
- getName() 這個方法返回每個 IComponent 對應的實例key值,方便在不同的模塊我們可以根據這個key值找到對應的 IComponent 對象
其次,如何調用呢?
1
|
ComponentController.getComponentByName( "app" ).startComponent( null ); |
是的,只要根據app這個key值我們就能輕易的找到對應的 IComponent 對象,從而執行 startComponent ,這個方法就是你想要在該模塊做的邏輯地方。
看上面我們聲明的 AppComponent 類,我們在 startComponent 有判斷一下傳入的參數是否為空,這里直接放了一個偽 Map 類專門用于存放傳遞的參數。
如何回調結果以及如何獲取別的模塊的回調結果?
首先你執行了別的模塊的 startComponent 方法,在這個方法中你返回的類肯定只有對應的模塊能識別,也就是說你在自己模塊獲取不到別的模塊中的類,所以這里使用 ComponentParam 采用key/value的風格存放參數以及回調返回結果,然后看一下下面的代碼就能明白答案了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
// 傳遞參數給IComponent, 可以通過傳遞回調函數從而得到回調結果 Map<String, Object> p = new HashMap<>(); p.put( "callback" , new ICallBack() { @Override public void onComponentBack(ComponentParam result) { Log.w( "Jayuchou" , "==== 運行結果 = " + result.getParam().get( "result" )); } }); ComponentParam cp = new ComponentParam(p); // 回調結果回去 ICallBack callBack = (ICallBack) param.getParam().get( "callback" ); Map<String, Object> results = new HashMap<>(); results.put( "result" , "我來自AppComponent" ); ComponentParam cp = new ComponentParam(results); callBack.onComponentBack(cp); // 調用的時候傳入參數即可 ComponentController.getComponentByName( "app" ).startComponent(cp); |
路由跳轉
首先,老規矩肯定也是聲明一下路由協議(這里只是一個簡單的字符串)
1
2
3
4
5
6
7
8
|
@NeacyProtocol ( "/activity/a" ) public class AActivity extends AppCompatActivity @NeacyProtocol ( "/activity/b" ) public class BActivity extends AppCompatActivity @NeacyProtocol ( "/activity/app" ) public class MainActivity extends AppCompatActivity |
然后調用就是了:
1
2
3
4
5
|
RouterController.startRouter(MainActivity. this , "/activity/a" ); // 跳轉到AActivity Bundle args = new Bundle(); args.putString( "key" , "AActivity" ); RouterController.startRouter(AActivity. this , "/activity/b" , args); // 跳轉到BActivity并攜帶bundle參數 |
原理
原理就是通過gradle插件結合ASM掃描注解并在編譯的時候注入代碼,我們先看下注入成功后的代碼結構:
1.模塊通信的注入結果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public class ComponentController { static { registerComponent( new AComponent()); registerComponent( new BComponent()); registerComponent( new AppComponent()); } private static Map<String, IComponent> components = new HashMap(); static void registerComponent(IComponent component) { components.put(component.getName(), component); } . . . } |
2.路由跳轉注入結果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public class RouterController { static { addRouter( "/activity/a" , "com.neacy.neacy_a.AActivity" ); addRouter( "/activity/b" , "com.neacy.neacy_b.BActivity" ); addRouter( "/activity/app" , "com.neacy.component.MainActivity" ); } private static Map<String, String> routers = new HashMap(); public static void addRouter(String key, String value) { routers.put(key, value); } } |
3.更多gradle插件的代碼查閱 https://github.com/Neacy/NeacyComponent
最后
再次感謝靈感: https://github.com/luckybilly/CC
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://www.jianshu.com/p/e5fdacdd4488