延續上一篇 MonkeyLei:Android-模塊化、組件化、插件化、熱修復-組件化工程構建+頁面路由多種方式實踐 ,我們進行搞下組件之間的通信。比如登錄成功后怎么通知其他頁面刷新:
方式可能有很多,列舉幾種:
- sharedpreferences,這種適合一些長期本地存儲的值(比如用戶登錄賬號信息)
- basemodule里面新建一個公共數據類,存儲全局數據,臨時通信時使用,提供set/get方法,就是所謂的下沉到底層模塊
- 基于上一篇的IAppComponent接口,擴展數據存儲接口,在每個模塊的XxxxApplication類提供數據給其他模塊,但是只能達到該Application類,還是需要通知到其他指定頁面
- greenrobot/EventBus通知刷新(比較簡單好用,有時候需要注意是不是采用黏性廣播)
- alibaba/ARouter 的接口調用方式(首次使用了下,猜想了下感覺就是維護了一個指定path的接口對象,而且還是個單例的接口對象,之后始終只有一個該實例被使用;而且該接口還限制了必須是實現了IProvider,只有該IProvider類型才能編譯通過;回頭瞅瞅源碼就造了)
- 可能還有其他方式吧~~~
直接看代碼,注釋都寫了:
a0.注意別忘記引入Eventbus庫
a1. base模塊定義一些Eventbus的事件類,以及Arouter的Provider接口
a2. 然后login模塊里面實現Arouter數據接口
login/src/.../LoginProvider.java - 添加@Route注解
package com.skl.login;
import android.content.Context;
import android.util.Log;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.skl.basemodule.common_interface.IDataCallBack;
@Route(path = "/login/provider")
public class LoginProvider implements IDataCallBack {
private Object content;
@Override
public void setSomething(Object obj) {
this.content = obj;
}
@Override
public Object getSomething() {
return content;
}
@Override
public void init(Context context) {
// TODO 可以在init方法中進行一些接口首次被調用時的初始化操作
Log.e("LoginProvider", "init!");
}
}
a3. 完事了,我們就可以點擊登錄,然后成功后采用各種方式進行通知(有些方式做個說明就行,具體自己可以簡單試試);
login/src/.../LoginActivity.java
/**
* 登錄 + 可以保存數據到本地(采用sharedpreferences的方式存儲)
* TODO 注意:這里為了模擬組件間的接口調用,采用其他方式
*
* @param view
*/
public void logining(View view) {
// -通知個人中心刷方式1\. 登錄成功后,本地保存登錄信息,每次切換到個人中心頁面都進行個人信息刷新;解決:采用Sharedpreferences存儲
// --通知個人中心刷方式1.1.下沉到底層模塊basemodule里,所有業務組件可依賴,這樣就解決了組件之間數據共享的問題; 解決:類似CompomentsService那樣定義公共類,提供公共開放靜態接口(set/get)...
// -通知個人中心刷方式2\. 主動調用刷新; 解決:其實也是通過擴展IAppComponent接口,但是只能到達組件的XxxxApplication類,還是需要通知到指定頁面
// -TODO 通知個人中心刷新方式3\. Eventbus通知刷新
EventBus.getDefault().post(new MessageEvent("login_success", "name:hl,age:22"));
// -TODO 通知個人中心刷方式4\. ARouter路由通信 - 這里路由設置相關信息,個人中心獲取進行刷新
IDataCallBack provider = (IDataCallBack) ARouter.getInstance().build("/login/provider").navigation();
if (null != provider) {
provider.setSomething("name:hl,age:22");
}
finish();
// TODO - 這里用登錄成功來演示了一下組件的通信,但是要注意的是:
// 我們登錄成功的信息是持久化的,需要shared保存的哈,不然每次重新進入就沒了!
}
a4. 然后主頁面,以及個人信息展示頁面均可以注冊Eventbus事件,或者通過Arouter方式的IDataCallBack接口對象來獲取數據
app/src/.../MainActivity.java - 部分代碼
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
}
/**
* Eventbus接收登錄等通知事件
* @param event
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
if (event.getKey().equals("login_success")){
Log.e("MainActivity", "user_info=" + event.getContent());
}
}
@Override
protected void onStart() {
super.onStart();
Log.e("MainActivity", "onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.e("MainActivity", "onResume");
IDataCallBack provider = (IDataCallBack) ARouter.getInstance().build("/login/provider").navigation();
if (null != provider){
Log.e("MainActivity", "user_info=" + provider.getSomething());
// TODO 此時可以獲取數據設置到界面,這里我們演示ARoute的這個接口調用來實現組件通信哈!!
// 如果采用Eventbus貌似就不用每次這里做判斷了
}
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
personal/src/...PersonalActivity.java
package com.skl.personal;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import com.skl.basemodule.common_interface.IDataCallBack;
@Route(path = "/ppx/personal")
public class PersonalActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_personal);
}
/**
* 獲取登錄頁面個人信息并展示
* @param view
*/
public void getLoginInfo(View view) {
IDataCallBack provider = (IDataCallBack) ARouter.getInstance().build("/login/provider").navigation();
if (null != provider){
((TextView)view).setText("" + provider.getSomething());
}
}
}
[圖片上傳中...(image-67da36-1570520271713-0)]
我看了下,大部分好像都是Eventbus或者路由。。像登錄注冊可能更多的是share存儲。下沉到基礎模塊的情況應該也是看哪些數據,根據項目實際情況,我們需要酌情選擇清晰易維護的實現方式。適合的才是最好的?
工程地址: https://gitee.com/heyclock/doc/tree/master/組件化
如果采用Arouter,有必須深入下一些用法:
https://blog.csdn.net/panyongjie2577/article/details/89344394
https://blog.csdn.net/superxlcr/article/details/77966142
https://blog.csdn.net/hzw2017/article/details/84204833
厲害點的,自己琢磨分析封裝路由,參考Arouter或者WMRouter
http://www.lxweimin.com/p/82b994fe532c
組件化的工作,首先工程的構建(app,basemodule,application/library's module, and other library),其次路由相關配置,然后組件通信。這是主要的三個工作,我們采用三方庫,最終目的也是為了讓組件的通信不產生耦合,直觀的感受就是隨時可以剝離到一個組件的依賴,而不會影響程序的編譯運行....組件化比較適合多人協同開發,像我們大部分都是一個人,兩個人,或許就不用搞什么組件化了,頂多就是app模塊下分多子模塊進行開發,以后如果想剝離為組件,多子模塊還是有好處的!
早期的我們有時候都不搞子模塊,頁面統一放到app/src/..../actiivty、或者app/src/..../fragment,適配器放到app/src/..../adapter。。。總之就是一堆就是了。。。隨著技術項目經驗的沉淀,還是需要有一定的改變和提升才行!??!有一天我們還是會搞大項目的,只要堅持學習,努力提升自己,我目前比菜,也是從去年徹底投入android,也希望可以自律,努力堅持,一起加油吧!我目前一般都是爭取看官方的,然后結合網友的,推薦優先官方走起。到一定階段,可以抽時間看源碼!
就這樣吧,一起努力....