EventBus之簡單用法

什麼是EventBus

先不去看官方的理解,我個人理解爲就是在任何你想和UI線程傳遞數據時候他都能給你進行數據傳遞,UI線程和傳輸數據的子線程是高度解耦合的,可以說是相當流氓,想怎麼傳數據就怎麼傳數據。

用法

用法比較簡單,首先在build.gradle裏添加

 compile 'org.greenrobot:eventbus:3.0.0'

這裏爲了方便使用,同時添加了butterKnife的依賴,butterKnife的使用請自行百度

  • 先聲明事件消息的實體類,並寫一個get方法
public class MyEvent {

    private String msg ;
    public MyEvent(String msg) {

        this.msg= msg;
    }  
    public String getMsg(){
        return msg;
    }  
}  
  • 接下來我們創建兩個Activity,一個作爲接收方的MainActivity,另一個作爲發送方的SecondActivity

MainActivity

public class MainActivity extends AppCompatActivity {
    @BindView(R.id.tv_1)       
    TextView tv_1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        EventBus.getDefault().register(this);  //在要接收消息的地方註冊EventBus
    }

    @OnClick(R.id.btn_1)
    public void onTest(View view){

        Intent intent = new Intent(MainActivity.this,SecondActivity.class);
        startActivity(intent);      //跳轉到SecondActivity

    }
    //收到SecondActivity發送的消息
    @Subscribe
    public void onMessageEvent(MyEvent event){
        String msg = event.getMsg();
        tv_1.setText(msg);    //將收到的消息輸入TextView
        Toast.makeText(MainActivity.this,msg,Toast.LENGTH_SHORT).show();
    }
 }

@Override
    protected void onDestroy(){
        super.onDestroy();
        EventBus.getDefault().unregister(this);//註銷EventBus
    }

SecondActivity

public class SecondActivity extends AppCompatActivity {
     @BindView(R.id.et_2)
    EditText et_2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        ButterKnife.bind(this);
    }

    @OnClick(R.id.btn_2)
    public void onTest2(View view){
            String str = et_2.getText().toString();   //獲取EditText內容
            EventBus.getDefault().post(new MyEvent(str));  //發送消息給MainActivity
            super.onBackPressed();     //調用返回鍵回到MainActivity
    }

}

兩個佈局文件
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.eventbusdemo.MainActivity">

    <TextView
        android:id="@+id/tv_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
   />


    <Button
        android:id="@+id/btn_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="跳轉到第二個界面"/>

</LinearLayout>

activity_second.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.eventbusdemo.SecondActivity">

    <EditText
        android:id="@+id/et_2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btn_2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="向第一個頁面發送消息,並顯示在TextView上"/>
</LinearLayout>

運行結果如下:
這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

這樣就完成了一個簡單的使用EventBus來傳遞消息的Demo

EventBus的線程模式

EventBus有四種線程模式:

  • ThreadMode: POSTING
    這時候訂閱者執行的線程與事件的發佈者所在的線程爲同一個線程。也就是說事件由哪個線程發佈的,訂閱者就在哪個線程中執行。這個也是EventBus默認的線程模式,也就是說在上面的例子中用的就是這種ThreadMode。由於沒有線程的切換,也就意味消耗的資源也是最小的。如果一個任務不需要多線程的,也是推薦使用這種ThreadMode的。在EventBus以前的版本中對應onEvent方法。例如:
 @Subscribe
    public void onMessageEvent(MyEvent event){
        ........
    }

或者

 @Subscribe(threadMode = ThreadMode.POSTING)
    public void onMessageEvent(MyEvent event){
       .........
    }
  • ThreadMode: MAIN
    從它的名字就很容易可以看出,他是在Android的主線程中運行的。如果提交的線程也是主線程,那麼他就和ThreadMode.POSTING一樣了。當然在這裏由於是在主線程中運行的,所以在這裏就不能執行一些耗時的任務。在EventBus以前的版本中對應onEventMainThread方法。例如:
//在Android主線程中執行
 @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(MyEvent event){
       .........
    }
  • ThreadMode: BACKGROUND
    這種模式下,我們的訂閱者將會在後臺線程中執行。如果發佈者是在主線程中進行的事件發佈,那麼訂閱者將會重新開啓一個子線程運行,若是發佈者在不是在主線程中進行的事件發佈,那麼這時候訂閱者就在發佈者所在的線程中執行任務。在EventBus以前的版本中對應onEventBackground方法。例如:
//在後臺線程中執行
@Subscribe(threadMode = ThreadMode.BACKGROUND)
    public void onMessageEvent(MyEvent event){
       .........
    }
  • ThreadMode: ASYNC
    在這種模式下,訂閱者將會獨立運行在一個線程中。不管發佈者是在主線程還是在子線程中進行事件的發佈,訂閱者都是在重新開啓一個線程來執行任務。在EventBus以前的版本中對應onEventAsync方法。例如:
// 在獨立的線程中執行
@Subscribe(threadMode = ThreadMode.ASYNC)
    public void onMessageEvent(MyEvent event){
       .........
    }

具體例子不貼上來,根據實際情況調用就好

消息接收的優先級與取消事件

在EventBus中是可以定義接收消息的優先級的,就是指定誰先接收,誰後接收
用法如下:

   //這裏使用默認的接收線程方式,不指定線程,根據發送方來確定
    @Subscribe(priority = 1)
    public void onMessageEvent1(MyEvent event){

        Log.d("1", "1收到了消息");
    }

那麼我們就可以寫出這樣的例子:

public class MainActivity extends AppCompatActivity {
    @BindView(R.id.tv_1)
    TextView tv_1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        EventBus.getDefault().register(this);
    }

    @OnClick(R.id.btn_1)
    public void onTest(View view){

        Intent intent = new Intent(MainActivity.this,SecondActivity.class);
        startActivity(intent);

    }

    @Subscribe(priority = 1)
    public void onMessageEvent1(MyEvent event){

        Log.d("1", "1收到了消息");

    }
    @Subscribe(priority = 2)
    public void onMessageEvent2(MyEvent event){
        Log.d("2", "2收到了消息");
    }

    @Subscribe(priority = 3)
    public void onMessageEvent3(MyEvent event){
        Log.d("3", "3收到了消息");
        EventBus.getDefault().cancelEventDelivery(event);      //取消事件
    }

    @Subscribe(priority = 4)
    public void onMessageEvent4(MyEvent event){
        Log.d("4", "4收到了消息");
    }

    @Subscribe(priority = 5)
    public void onMessageEvent5(MyEvent event){
        Log.d("5", "5收到了消息");
    }

    @Override
    protected void onDestroy(){
        super.onDestroy();
        EventBus.getDefault().unregister(this);//註銷EventBus
    }

}

從上面的代碼可以看出,我們定義了一系列的接收事件,並給它們定義優先級,並在優先級爲3的接收事件中取消消息發送事件,那麼執行的結果如下:
這裏寫圖片描述

可以看出 優先級爲 2 和 1 的事件確實沒有接收到消息。

本文講解就到這裏,之後會陸續補充內容

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章