Android中EventBus的使用

什么是EventBus

EventBus是Android下高效的發(fā)布/訂閱事件總線機制。作用是可以代替?zhèn)鹘y(tǒng)的Intent,Handler,Broadcast或接口函數(shù)在Fragment,Activity,Service,線程之間傳遞數(shù)據(jù),執(zhí)行方法,也可以通過調(diào)用普通類開啟發(fā)送消息。特點是代碼簡潔,是一種發(fā)布訂閱設(shè)計模式(Publish/Subsribe),或稱作觀察者設(shè)計模式。

如何使用EventBus

EventBus.png
  1. Publisher是發(fā)布者, 通過post()方法將消息事件Event發(fā)布到事件總線
  2. EventBus是事件總線, 遍歷所有已經(jīng)注冊事件的訂閱者們,找到里邊的onEvent等4個方法,分發(fā)Event
  3. Subscriber是訂閱者, 收到事件總線發(fā)下來的消息。即onEvent方法被執(zhí)行。注意參數(shù)類型必須和發(fā)布者發(fā)布的參數(shù)一致。

MainActivity.java

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
   }
}

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:divider="?android:attr/dividerHorizontal"
    android:orientation="horizontal"
    android:showDividers="middle"
    android:baselineAligned="false"
    tools:context="com.itheima.eventbusdemo.MainActivity" >
    <fragment
        android:id="@+id/left_fragment"
        android:name="com.itheima.eventbusdemo.LeftFragment"
        android:layout_width="0dip"
        android:layout_height="match_parent"
        android:layout_weight="1" />
    <fragment
        android:id="@+id/right_fragment"
        android:name="com.itheima.eventbusdemo.RightFragment"
        android:layout_width="0dip"
        android:layout_height="match_parent"
        android:layout_weight="3" />
</LinearLayout>

fragment_left.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <Button
        android:id="@+id/bt"
        android:textSize="14sp"
        android:layout_centerInParent="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="按鈕" />
</RelativeLayout>

fragment_right.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <Button
        android:id="@+id/bt"
        android:textSize="14sp"
        android:layout_centerInParent="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="按鈕" />
</RelativeLayout>

LeftFragment.java

import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import de.greenrobot.event.EventBus;
public class LeftFragment extends ListFragment {
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        String[] strs = new String[]{"主線程消息1", "子線程消息1", "主線程消息2","通過普通類發(fā)送消息"};
        setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, strs));
    }
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        switch (position) {
            case 0:
                // 主線程
                System.out.println("----------------------主線程發(fā)的消息1"
                        + " threadName: "+ Thread.currentThread().getName()
                        + " threadId: " + Thread.currentThread().getId());
                EventBus.getDefault().post(new MsgEvent1("主線程發(fā)的消息1"));
                break;
            case 1:
                // 子線程
                new Thread(){
                    public void run() {
                        System.out.println("----------------------子線程發(fā)的消息1"
                                + " threadName: "+ Thread.currentThread().getName()
                                + " threadId: " + Thread.currentThread().getId());
                        EventBus.getDefault().post(new MsgEvent1("子線程發(fā)的消息1"));
                    };
                }.start();
                break;
            case 2:
                // 主線程
                System.out.println("----------------------主線程發(fā)的消息2"
                        + " threadName: "+ Thread.currentThread().getName()
                        + " threadId: " + Thread.currentThread().getId());
                EventBus.getDefault().post(new MsgEvent2("主線程發(fā)的消息2"));
                break;
            case 3:
                // 子線程2
                new Thread(){
                    public void run() {
                        System.out.println("----------------------子線程發(fā)的類EventBus1消息1"
                                + " threadName: "+ Thread.currentThread().getName()
                                + " threadId: " + Thread.currentThread().getId());
                        new EventBus1();//調(diào)用類EventBus1傳送消息
                    }
                }.start();
        }
    }
}

RightFragment.java

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import de.greenrobot.event.EventBus;
public class RightFragment extends Fragment {
    private TextView tv;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 界面創(chuàng)建時,訂閱事件, 接受消息
        EventBus.getDefault().register(this);
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        // 界面銷毀時,取消訂閱
        EventBus.getDefault().unregister(this);
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_right, null);
        tv = (TextView) view.findViewById(R.id.tv);
        return view;
    }
    /**
     * 與發(fā)布者在同一個線程
     * @param msg 事件1
     */
    public void onEvent(MsgEvent1 msg){
        String content = msg.getMsg()
                + "\n ThreadName: " + Thread.currentThread().getName()
                + "\n ThreadId: " + Thread.currentThread().getId()+"\n onEvent";
        System.out.println("onEvent(MsgEvent1 msg)收到" + content);
    }
    /**
     * 執(zhí)行在主線程。
     * 非常實用,可以在這里將子線程加載到的數(shù)據(jù)直接設(shè)置到界面中。
     * @param msg 事件1
     */
    public void onEventMainThread(MsgEvent1 msg){
        String content = msg.getMsg()
                + "\n ThreadName: " + Thread.currentThread().getName()
                + "\n ThreadId: " + Thread.currentThread().getId()+"\n onEventMainThread";
        System.out.println("onEventMainThread(MsgEvent1 msg)收到" + content);
        tv.setText(content);
    }
    /**
     * 執(zhí)行在子線程,如果發(fā)布者是子線程則直接執(zhí)行,如果發(fā)布者不是子線程,則創(chuàng)建一個再執(zhí)行
     * 此處可能會有線程阻塞問題。
     * @param msg 事件1
     */
    public void onEventBackgroundThread(MsgEvent1 msg){
        String content = msg.getMsg()
                + "\n ThreadName: " + Thread.currentThread().getName()
                + "\n ThreadId: " + Thread.currentThread().getId()+"\n onEventBackgroundThread";
        System.out.println("onEventBackgroundThread(MsgEvent1 msg)收到" + content);
    }
    /**
     * 執(zhí)行在在一個新的子線程
     * 適用于多個線程任務(wù)處理, 內(nèi)部有線程池管理。
     * @param msg 事件1
     */
    public void onEventAsync(MsgEvent1 msg){
        String content = msg.getMsg()
                + "\n ThreadName: " + Thread.currentThread().getName()
                + "\n ThreadId: " + Thread.currentThread().getId()+"\n onEventAsync";
        System.out.println("onEventAsync(MsgEvent1 msg)收到" + content);
    }
    /**
     * 與發(fā)布者在同一個線程
     * @param msg 事件2
     */
    public void onEvent(MsgEvent2 msg){
        String content = msg.getMsg()
                + "\n ThreadName: " + Thread.currentThread().getName()
                + "\n ThreadId: " + Thread.currentThread().getId()+"\n msg2";
        System.out.println("onEvent(MsgEvent2 msg)收到" + content);
        tv.setText(content);
    }
}

MsgEvent1.java

public class MsgEvent1 {
    private String msg;
    
    public MsgEvent1(String msg) {
        super();
        this.msg = msg;
    }
    public String getMsg() {
        return msg;
    }
}

MsgEvent2.java

public class MsgEvent2 {
    private String msg;
    
    public MsgEvent2(String msg) {
        super();
        this.msg = msg;
    }
    public String getMsg() {
        return msg;
    }
}

EventBus1.java

import de.greenrobot.event.EventBus;
public class EventBus1 {
    public EventBus1() {
        // TODO Auto-generated constructor stub
        EventBus.getDefault().post(new MsgEvent1("類EventBus1發(fā)的消息1"));
    }
}
效果圖:
效果圖.gif

源碼地址:https://git.oschina.net/Fly321/EventBus.git

EventBus的ThreadMode

EventBus包含4個ThreadMode:PostThread,MainThread,BackgroundThread,Async
MainThread我們已經(jīng)不陌生了;我們已經(jīng)使用過。
具體的用法,極其簡單,方法名為:onEventPostThread, onEventMainThread,onEventBackgroundThread,onEventAsync即可
具體什么區(qū)別呢?

  • onEventMainThread代表這個方法會在UI線程執(zhí)行
  • onEventPostThread代表這個方法會在當(dāng)前發(fā)布事件的線程執(zhí)行
  • BackgroundThread這個方法,如果在非UI線程發(fā)布的事件,則直接執(zhí)行,和發(fā)布在同一個線程中。如果在UI線程發(fā)布的事件,則加入后臺任務(wù)隊列,使用線程池一個接一個調(diào)用。

Async 加入后臺任務(wù)隊列,使用線程池調(diào)用,注意沒有BackgroundThread中的一個接一個。

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

相關(guān)閱讀更多精彩內(nèi)容

  • 最近在項目中使用了EventBus(3.0),覺得非常好用,于是就看了一些關(guān)于EventBus源碼分析的文章,現(xiàn)在...
    shenhuniurou閱讀 1,581評論 0 4
  • 一、簡介 EventBus是由greenrobot 組織貢獻(xiàn)的一個Android事件發(fā)布/訂閱輕量級框架。Even...
    Mr丶sorrow閱讀 15,390評論 0 13
  • 先吐槽一下博客園的MarkDown編輯器,推出的時候還很高興博客園支持MarkDown了,試用了下發(fā)現(xiàn)支持不完善就...
    Ten_Minutes閱讀 651評論 0 2
  • Android 淺析EventBus (一) 使用 前言 Linus Benedict Torvalds : RT...
    CodePlayer_Jz閱讀 3,485評論 3 10
  • 魚,我所欲也,熊掌,亦我所欲也,二者不可兼得,舍魚而取熊掌者也。生,亦我所欲也,義,亦我所欲也,二者不可兼得,舍生...
    識學(xué)閱讀 451評論 0 0

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