Android-模塊化、組件化、插件化、熱修復(fù)-組件化-組件間的通信(本地,下沉,bus,路由)

延續(xù)上一篇 MonkeyLei:Android-模塊化、組件化、插件化、熱修復(fù)-組件化工程構(gòu)建+頁面路由多種方式實(shí)踐 ,我們進(jìn)行搞下組件之間的通信。比如登錄成功后怎么通知其他頁面刷新:

方式可能有很多,列舉幾種:

  1. sharedpreferences,這種適合一些長(zhǎng)期本地存儲(chǔ)的值(比如用戶登錄賬號(hào)信息)
  2. basemodule里面新建一個(gè)公共數(shù)據(jù)類,存儲(chǔ)全局?jǐn)?shù)據(jù),臨時(shí)通信時(shí)使用,提供set/get方法,就是所謂的下沉到底層模塊
  3. 基于上一篇的IAppComponent接口,擴(kuò)展數(shù)據(jù)存儲(chǔ)接口,在每個(gè)模塊的XxxxApplication類提供數(shù)據(jù)給其他模塊,但是只能達(dá)到該Application類,還是需要通知到其他指定頁面
  4. greenrobot/EventBus通知刷新(比較簡(jiǎn)單好用,有時(shí)候需要注意是不是采用黏性廣播)
  5. alibaba/ARouter 的接口調(diào)用方式(首次使用了下,猜想了下感覺就是維護(hù)了一個(gè)指定path的接口對(duì)象,而且還是個(gè)單例的接口對(duì)象,之后始終只有一個(gè)該實(shí)例被使用;而且該接口還限制了必須是實(shí)現(xiàn)了IProvider,只有該IProvider類型才能編譯通過;回頭瞅瞅源碼就造了)
  6. 可能還有其他方式吧~~~

直接看代碼,注釋都寫了:

a0.注意別忘記引入Eventbus庫

image
image
image

a1. base模塊定義一些Eventbus的事件類,以及Arouter的Provider接口

image
image

a2. 然后login模塊里面實(shí)現(xiàn)Arouter數(shù)據(jù)接口

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方法中進(jìn)行一些接口首次被調(diào)用時(shí)的初始化操作
        Log.e("LoginProvider", "init!");
    }
}

a3. 完事了,我們就可以點(diǎn)擊登錄,然后成功后采用各種方式進(jìn)行通知(有些方式做個(gè)說明就行,具體自己可以簡(jiǎn)單試試);

login/src/.../LoginActivity.java

   /**
     * 登錄 + 可以保存數(shù)據(jù)到本地(采用sharedpreferences的方式存儲(chǔ))
     * TODO 注意:這里為了模擬組件間的接口調(diào)用,采用其他方式
     *
     * @param view
     */
    public void logining(View view) {
        // -通知個(gè)人中心刷方式1\. 登錄成功后,本地保存登錄信息,每次切換到個(gè)人中心頁面都進(jìn)行個(gè)人信息刷新;解決:采用Sharedpreferences存儲(chǔ)
        // --通知個(gè)人中心刷方式1.1.下沉到底層模塊basemodule里,所有業(yè)務(wù)組件可依賴,這樣就解決了組件之間數(shù)據(jù)共享的問題;  解決:類似CompomentsService那樣定義公共類,提供公共開放靜態(tài)接口(set/get)...
        // -通知個(gè)人中心刷方式2\. 主動(dòng)調(diào)用刷新; 解決:其實(shí)也是通過擴(kuò)展IAppComponent接口,但是只能到達(dá)組件的XxxxApplication類,還是需要通知到指定頁面
        // -TODO 通知個(gè)人中心刷新方式3\. Eventbus通知刷新
        EventBus.getDefault().post(new MessageEvent("login_success", "name:hl,age:22"));
        // -TODO 通知個(gè)人中心刷方式4\. ARouter路由通信 - 這里路由設(shè)置相關(guān)信息,個(gè)人中心獲取進(jìn)行刷新
        IDataCallBack provider = (IDataCallBack) ARouter.getInstance().build("/login/provider").navigation();
        if (null != provider) {
            provider.setSomething("name:hl,age:22");
        }
        finish();
        // TODO - 這里用登錄成功來演示了一下組件的通信,但是要注意的是:
        //        我們登錄成功的信息是持久化的,需要shared保存的哈,不然每次重新進(jìn)入就沒了!
    }

a4. 然后主頁面,以及個(gè)人信息展示頁面均可以注冊(cè)Eventbus事件,或者通過Arouter方式的IDataCallBack接口對(duì)象來獲取數(shù)據(jù)

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 此時(shí)可以獲取數(shù)據(jù)設(shè)置到界面,這里我們演示ARoute的這個(gè)接口調(diào)用來實(shí)現(xiàn)組件通信哈!!
            //      如果采用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);
    }

    /**
     * 獲取登錄頁面?zhèn)€人信息并展示
     * @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或者路由。。像登錄注冊(cè)可能更多的是share存儲(chǔ)。下沉到基礎(chǔ)模塊的情況應(yīng)該也是看哪些數(shù)據(jù),根據(jù)項(xiàng)目實(shí)際情況,我們需要酌情選擇清晰易維護(hù)的實(shí)現(xiàn)方式。適合的才是最好的?

工程地址: 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

厲害點(diǎn)的,自己琢磨分析封裝路由,參考Arouter或者WMRouter

http://www.itdecent.cn/p/82b994fe532c

組件化的工作,首先工程的構(gòu)建(app,basemodule,application/library's module, and other library),其次路由相關(guān)配置,然后組件通信。這是主要的三個(gè)工作,我們采用三方庫,最終目的也是為了讓組件的通信不產(chǎn)生耦合,直觀的感受就是隨時(shí)可以剝離到一個(gè)組件的依賴,而不會(huì)影響程序的編譯運(yùn)行....組件化比較適合多人協(xié)同開發(fā),像我們大部分都是一個(gè)人,兩個(gè)人,或許就不用搞什么組件化了,頂多就是app模塊下分多子模塊進(jìn)行開發(fā),以后如果想剝離為組件,多子模塊還是有好處的!

早期的我們有時(shí)候都不搞子模塊,頁面統(tǒng)一放到app/src/..../actiivty、或者app/src/..../fragment,適配器放到app/src/..../adapter。。??傊褪且欢丫褪橇?。。。隨著技術(shù)項(xiàng)目經(jīng)驗(yàn)的沉淀,還是需要有一定的改變和提升才行!??!有一天我們還是會(huì)搞大項(xiàng)目的,只要堅(jiān)持學(xué)習(xí),努力提升自己,我目前比菜,也是從去年徹底投入android,也希望可以自律,努力堅(jiān)持,一起加油吧!我目前一般都是爭(zhēng)取看官方的,然后結(jié)合網(wǎng)友的,推薦優(yōu)先官方走起。到一定階段,可以抽時(shí)間看源碼!

就這樣吧,一起努力....

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容