Android--Otto事件匯流排 -- 組件之間通訊架構使用 --模式解析

來源:互聯網
上載者:User
前言:Otto事件匯流排 -- 組件之間通訊架構對於之前的情況activity之間或者fragment之間等跳轉傳值一般都是用bundle、intent等,從activityA --- activityB用startActivity,用startActivityForResult()可以接受後者回到前者的參數並且可做一些更新UI等操作。這樣一來就要判斷從A中哪一個按鈕跳轉到了B,就要設定唯一標識定義什麼FRIST=1,FFFFF=2等。Otto事件匯流排解決了這個問題,只要在訂閱事件,接收方接受訂閱,傳實值型別為唯一標示。這樣子只要在觸發了post後,接受方就會執行指定方法,就算不返回到A介面也是可以執行的。使用Otto事件匯流排架構的原因
  1. 一般情況下,在Android中的Activity與Activity之間值的傳遞,我們通過Intent的方式;
  2. Activity與Fragment之間我們通過setArguments,值回調我們是在Fragment中的onAttach()介面方式實現;
  3. Activity與service之間,我們通常會使用binder機制,但是binder機制實際上使用的也是介面回調的方式;
  4. 在一些比較複雜的情況,比如Activity嵌套多個Fragment頁面的時候,如果一個頁面的值發生了改變,其他的頁面也要跟著發生資料的更新操作,這樣我們會頻繁的使用介面回調的方式,這種方式的耦合性太高。
Otto事件的模式

對於一個如此方便的架構,Java模式的加入是必不可少的,無論是Rxjava(觀察者模式擴充)還是EventBus都有觀察者模式,所以中間講解該模式。

一、簡單使用
  • @Subscribe:這個在調用了register後有效,表示訂閱了一個事件,並且方法的用 public 修飾的.方法名可以隨意取,重點是參數,它是根據你的參數進行判斷
  • @Produce註解告訴Bus該函數是一個事件產生者,產生的事件類型為該函數的傳回值。
 1-1:添加依賴
dependencies {  compile 'com.squareup:otto:1.3.8'}或者//otto事件匯流排    compile 'com.squareup:otto:+'
1-2:訂閱和取消訂閱
bus.register(this);bus.unregister(this);發布:bus.post(new MessageEvent());註解@Subscribe:這個在調用了register後有效,表示訂閱了一個事件,並且方法的用 public 修飾的.方法名可以隨意取,重點是參數,它是根據你的參數進行判斷@Produce註解告訴Bus該函數是一個事件產生者,產生的事件類型為該函數的傳回值。最後,proguard 需要做一些額外處理,防止混淆:-keepattributes *Annotation*-keepclassmembers class ** {    @com.squareup.otto.Subscribe public *;    @com.squareup.otto.Produce public *;}
1-3:otto推薦使用單例模式,保證只有一個執行個體
public class BusProvider extends Bus {    /**     * 通過單例模式返回唯一的bus對象,而且重寫父類的post方法,通過handler實現任意線程可以調用     */    private Handler mHandler = new Handler(Looper.getMainLooper());    private static Bus bus = new BusProvider();        private BusProvider(){            }    public static Bus getInstance(){                return bus;    }        @Override    public void post(final Object event) {        if (Looper.myLooper() == Looper.getMainLooper()) {            super.post(event);        }else {            mHandler.post(new Runnable() {                @Override                public void run() {                    BusProvider.super.post(event);                }            });        }    }}
1-4:調用 A-->B@SubscribeactivityA:
/** * Created by 劉志通 on 2018/7/4. */public class OttoTestOne extends AppCompatActivity {    private Bus bus;    private Button button,button2;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.ottotwo_layout);         //訂閱        bus = BusProvider.getInstance();         bus.register(this);        button = findViewById(R.id.id_two);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent=new Intent(OttoTestOne.this,OttoTestTwo.class);                startActivity(intent);            }        });    }//註解接收String類型    @Subscribe    public void setText(String textstring) {        button.setText(textstring);        Log.e("檢測1",textstring+"");    }//接收bean類型    @Subscribe    public void setText2(EditBean textstring) {        button2.setText(textstring.getEdit1()+""+textstring.getEdit2());        Log.e("檢測2", textstring.getEdit1()+""+textstring.getEdit2());    }    /**     * 取消訂閱     * */    @Override    protected void onDestroy() {        BusProvider.getInstance().unregister(this);        super.onDestroy();    }}

 

activityB
/** * Created by 劉志通 on 2018/7/4. */public class OttoTestTwo extends AppCompatActivity {    private Bus bus;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        //擷取執行個體        bus = BusProvider.getInstance();        //註冊        bus.register(this);        setContentView(R.layout.ottoone_layout);        Button button=findViewById(R.id.id_btn);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                /*發送,這裡發送的是bean,也可以直接發送String類型的資料,接收則是A中String類型的接收。*/                EditBean editBean=new EditBean();                editBean.setEdit1("ni");                editBean.setEdit2(" hao");                editBean.setTotal(" ma");                bus.post(editBean);            }        });    }}
@Produce

只要有activity或者fragment跳轉到該頁面後,事件就會自動產生,然後在訂閱處(誰訂閱誰改變)更新一些資料。

       //擷取執行個體        bus = BusProvider.getInstance();        //註冊        bus.register(this);        setContentView(R.layout.ottothird_layout);    }    @Produce    public EditBean providerEvent(){        EditBean eventData = new EditBean();        eventData.setEdit1("hello world");        return eventData;    }    @Override    protected void onDestroy() {        super.onDestroy();        bus.unregister(this);    }
註:A->B中 @Produce模式則是在A中發起事件,也就是所謂的事件產生者,當從A跳轉到B後,如果B中有對EditBean有操作的話,就直接觸及到A的@Produce方法,並更新一些資料,這和Post比起來,有點簡單,因為你都不用再做任何操作,前一個介面就已經更新了,但Post可以控制何時發起事件,點擊按鈕後或者網路請求成功後直接bus.post(" ... ");二、觀察者模式前言觀察者模式(有時又被稱為模型-視圖(View)模式、源-收聽者(Listener)模式或從屬者模式)是軟體設計模式的一種。在此種模式中,一個目標物件管理所有相依於它的觀察者物件,並且在它本身的狀態改變時主動發出通知。這通常透過呼叫各觀察者所提供的方法來實現。此種模式通常被用來實現事件處理系統。需要注意:實現觀察者模式的時候要注意,觀察者和被觀察對象之間的互動關係不能體現成類之間的直接調用,否則就將使觀察者和被觀察對象之間緊密的耦合起來,從根本上違反物件導向的設計的原則。無論是觀察者“觀察”觀察對象,還是被觀察者將自己的改變“通知”觀察者,都不應該直接調用。觀察者(Observer)將自己註冊到被觀察對象(Subject)中,被觀察對象將觀察者存放在一個容器(Container)裡。被觀察被觀察對象發生了某種變化,從容器中得到所有註冊過的觀察者,將變化通知觀察者。撤銷觀察觀察者告訴被觀察者要撤銷觀察,被觀察者從容器中將觀察者去除。觀察者將自己註冊到被觀察者的容器中時,被觀察者不應該過問觀察者的具體類型,而是應該使用觀察者的介面。這樣的優點是:假定程式中還有別的觀察者,那麼只要這個觀察者也是相同的介面實現即可。一個被觀察者可以對應多個觀察者,當被觀察者發生變化的時候,他可以將訊息一一通知給所有的觀察者。基於介面,而不是具體的實現——這一點為程式提供了更大的靈活性。

舉例子:

這裡建立一個抽象觀察者(Observer)和一個被觀察者(Subject),然後繼承抽象觀察者,觀察者們通過觀察被觀察者(Subject)來改變自己。

建立類:
  • 抽象觀察者(Observer)
  • 被觀察者(Subject)
2-1:被觀察者Subject.java
public class Subject {    private List<Observer> observers            = new ArrayList<Observer>();    private Observer observer;    private int state;    //變更情況    public int getState() {        return state;    }    public void setState(int state) {        this.state = state;    }    //綁定    public void binding(Observer observer) {        observers.add(observer);    }    /**     * unbinding(登出觀察者,有時候在未擷取到執行個體使用)     **/    public void unbinding(Observer cls) {        if (cls == null) throw new NullPointerException();        observers.remove(cls);          }    //通知    public void notifyAllObservers() {        for (Observer observer : observers) {            observer.update();        }    }}

 

這裡需要注意的是如果是常規集合是不能直接用remove的,要如下轉換再行刪除。

  Iterator<Observer> iterator = observers.iterator();

 

2-2:觀察者(Observer)
/** * 觀察者 * */public abstract class Observer {    protected Subject subject;    public abstract void update();}
2-3:繼承Observer

需要注意的是,我這裡建立了3個如下類,只粘貼出一個,分別是FirstObserver,SecondObserver,ThirdObserver。

public class FirstObserver extends Observer {    public FirstObserver(Subject subject) {        this.subject = subject;        subject.binding(this);//綁定    }    @Override    public void update() {        //用來更新資料        System.out.println("我是第一個觀察者:"+subject.getState());    }}

 

2-4:測試

在主方法main中 這裡是在每個子類的構造方法中加入了綁定,所以,只要建立對象就已經綁定了,無序再次綁定,當然也是可以解除綁定的。

 //載入被觀察者        Subject subject = new Subject();        //載入觀察者        FirstObserver firstObserver = new FirstObserver(subject);        SecondObserver secondObserver = new SecondObserver(subject);        ThirdObserver thirdObserver = new ThirdObserver(subject);        subject.setState(2);        subject.notifyAllObservers();

 

解除綁定
subject.unbinding(secondObserver);        subject.setState(3);        subject.notifyAllObservers();

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.