当前位置: 首页 > 工具软件 > Otto > 使用案例 >

Android事件总线框架Otto使用介绍

寇和璧
2023-12-01

 Otto框架是square公司为Android出的一款事件总线框架,设计用于解耦应用程序的不同部分,同时仍然允许它们有效地通信。

https://github.com/square/otto

以下简单介绍一下Otto框架的使用方式:

创建Bus实例:

Bus bus = new Bus();

Otto在设计时考虑到了android特定的用例,建议使用单例模式使用(尽管这不是必需的),但是总线只有在共享时才有效。

package com.windfallsheng.myotto;

import com.squareup.otto.Bus;

public class OttoBus extends Bus {
    private volatile static OttoBus bus;

    private OttoBus() {
    }

    public static OttoBus getInstance() {
        if (bus == null) {
            synchronized (OttoBus.class) {
                if (bus == null) {
                    bus = new OttoBus();
                }
            }
        }
        return bus;
    }
}
public final class BusProvider {
    private static final Bus BUS = new Bus();

    public static Bus getInstance() {
        return BUS;
    }

    private BusProvider() {
        // No instances.
    }
}

发布事件 Publish:

通过调用 Bus 的 post 方法,告诉订阅者某个操作已经发生。任何类的实例都可以发布在总线上,并且它只会被分配给该类型的订阅者。

package com.windfallsheng.myotto;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

/**
 * Created by Administrator on 2016/11/17 0017.
 */

public class PostActivity extends AppCompatActivity {

    private static final String TAG = PostActivity.class.getSimpleName();
    private Button mBtnSendEventData;
    private String userArray[] = {"Cyra", "Morgen", "Iris", "Mia"};
    private String messageArray[] = {"我发表了新的美食文章", "我更新了我的相册", "我在FaceBook申请了账号", "我做了一个好看的小视频"};

    public static void start(Context context) {
        context.startActivity(new Intent(context, PostActivity.class));
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "method:onCreate");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_post);
        mBtnSendEventData = (Button) this.findViewById(R.id.btn_send_event_data);
        mBtnSendEventData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int uIndex = (int) (Math.random() * userArray.length);
                int mIndex = (int) (Math.random() * messageArray.length);
                EventData eventData = new EventData(userArray[uIndex], messageArray[mIndex]);
                Log.i(TAG, "method:onCreate#mBtnSendEventData#onClick#eventData#hashCode=" + eventData.hashCode());
                Log.i(TAG, "method:onCreate#mBtnSendEventData#onClick#eventData=" + eventData);
                OttoBus.getInstance().post(eventData);
//                finish();
            }
        });
    }
}
package com.windfallsheng.myotto;

public class EventData {

    public String userName;
    public String message;

    public EventData(String userName, String message) {
        this.userName = userName;
        this.message = message;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    @Override
    public String toString() {
        return "EventData{" +
                "userName='" + userName + '\'' +
                ", message='" + message + '\'' +
                '}';
    }
}

订阅Subscribe:

订阅后就可以接收到已经发出的事件,通过使用@Subscribe注释方法实现订阅。该方法应该只接受一个参数,该参数的类型是您希望订阅的事件。

package com.windfallsheng.myotto;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.squareup.otto.Subscribe;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = MainActivity.class.getSimpleName();
    private Button mBtnJumpToPost, mBtnJumpToProduce, mBtnJumpToMainActivity;
    private TextView mTvMessage, mTvMessageUpdate;

    public static void start(Context context) {
        context.startActivity(new Intent(context, MainActivity.class));
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTvMessage = (TextView) this.findViewById(R.id.tv_message);
        mTvMessageUpdate = (TextView) this.findViewById(R.id.tv_message_update);
        mBtnJumpToPost = (Button) this.findViewById(R.id.btn_jump_to_post);
        mBtnJumpToMainActivity = (Button) this.findViewById(R.id.btn_jump_to_main_activity);
        mBtnJumpToProduce = (Button) this.findViewById(R.id.btn_jump_to_produce);
        mBtnJumpToPost.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                PostActivity.start(MainActivity.this);
            }
        });
        mBtnJumpToProduce.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ProduceActivity.start(MainActivity.this);
            }
        });
        mBtnJumpToMainActivity.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MainActivity.start(MainActivity.this);
            }
        });
        Log.i(TAG, "method:onCreate#this#hashCode=" + this.hashCode());
        OttoBus.getInstance().register(this);
    }

    @Subscribe
    public void refreshMessage(EventData eventData) {
        Log.i(TAG, "method:Subscribe#refreshMessage#eventData#hashCode=" + eventData.hashCode());
        Log.i(TAG, "method:Subscribe#refreshMessage#eventData=" + eventData);
        mTvMessage.setText(eventData.getUserName() + ":\n\n" + eventData.getMessage());
    }

    @Subscribe
    public void updateMessage(EventData eventData) {
        Log.i(TAG, "method:updateMessage#updateMessage#eventData#hashCode=" + eventData.hashCode());
        Log.i(TAG, "method:Subscribe#updateMessage#eventData=" + eventData);
        mTvMessageUpdate.setText(eventData.getUserName() + ":\n\n" + eventData.getMessage());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        OttoBus.getInstance().unregister(this);
    }
}

使用@Subscribe注释的方法,它的名称可以是任意的,只需要满足注释、单参数和公共访问修饰符即可。

为了接收事件,类的实例还必须需向总线注册,比如示例中的注册方法:

OttoBus.getInstance().register(this);

另外,在适当的时候也要调用 unregister 方法。

 

发布事件的另一种方式:

通过生产 Produce 注解方式也可以发布事件,它与 post 方法不同的是,它在任何订阅者注册时立即向其提供回调。

要创建生产者,请使用@Produce注释方法。该方法不应接受任何参数,其返回类型将用作可以生成初始值的事件类型。

package com.windfallsheng.myotto;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.squareup.otto.Produce;

public class ProduceActivity extends AppCompatActivity {

    private static final String TAG = ProduceActivity.class.getSimpleName();
    private String userArray[] = {"Cyra", "Morgen", "Iris", "Mia"};
    private String messageArray[] = {"我发表了新的美食文章", "我更新了我的相册", "我在FaceBook申请了账号", "我做了一个好看的小视频"};

    public static void start(Context context) {
        context.startActivity(new Intent(context, ProduceActivity.class));
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "method:onCreate");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_produce);
        // 注册Otto
        Log.i(TAG, "method:onCreate#this#hashCode=" + this.hashCode());
        OttoBus.getInstance().register(this);
    }

    @Produce
    public EventData produceEventData() {
        Log.i(TAG, "method:Produce#produceEventData");
        int uIndex = (int) (Math.random() * userArray.length);
        int mIndex = (int) (Math.random() * messageArray.length);
        EventData eventData = new EventData(userArray[uIndex], messageArray[mIndex]);
        Log.i(TAG, "method:produceEventData#produceEventData#hashCode=" + eventData.hashCode());
        Log.i(TAG, "method:Produce#produceEventData#eventData=" + eventData);
        return eventData;
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "method:onResume");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "method:onDestroy");
        // 注销Otto
        OttoBus.getInstance().unregister(this);
    }
}

使用@Produce注释方法时,必须要调用 register 方法注释当前类实例,同时在适当的时机调用 unregister 方法。

在总线上,每次只能为每个事件类型注册一个生产者。

 

有关事件执行线程的问题:

由于有时您可能不清楚正在接收回调的线程是哪个,所以Otto提供了一种强制机制,以确保总是在您希望的线程上调用您。默认情况下,与实例的所有交互都仅限于主线程。

//这两者在功能上是等价的。
Bus bus1 = new Bus();
Bus bus2 = new Bus(ThreadEnforcer.MAIN);

如果您不关心发生在哪个线程上的交互,则使用 ThreadEnforcer.ANY 实例化一个总线实例。如果需要额外的功能或验证,还可以提供自己的 ThreadEnforcer 接口实现。

示例代码GitHub地址

官方使用说明

 

由于作者水平有限,语言描述及代码实现中难免有纰漏,望各位看官多提宝贵意见!

Hello , World !

感谢所有!

 类似资料: