Android事件总线框架Otto使用

     Otto框架是square公司为Android出的一款事件总线框架,主要是为了解决大项目中耦合性过高的问题,比如涉及到多个类都需要响应某一个操作,原始的做法就是使用广播,事件产生者发送广播,事件订阅者接收广播,并作出相应的操作,但是这样在项目越来越大后,就越来越不好维护和扩展,所以我们引进Otto这款框架,类似的还有一个Event BusOtto相比后者优势主要是上手什么简单,缺点是性能上会有一点差距,如果不在乎那一点差距完全可以使用Otto

    Github上有Otto的源码,十分的简洁,算上注解才9个类,实现的方式主要是依赖反射和注解,Otto上有两个注解,一个是Produce,一个是Subscribe。前面是事件产生者,后面是事件订阅者。当在一个方法中post一个事件时,会通过反射查找有Subsribe注解的类并进行调用。

    那有人可能会问了,通过广播的方式传值可以通过Bundle和Intent进行传值,那么Otto如何传值呢?

    作为一个成熟的框架肯定考虑到了这个问题,Otto中使用bus.post方法进行事件发布,参数是一个Object对象,只有一个参数,但是我们可以通过中间件的形式,比如传入一个javabean对象,中间包裹着参数,然后在订阅者中通过get方法得到值。
话说了这么久,还是先来看看实际的使用,因为是demo,就写的比较简单了,需求如下图

                                               Android事件总线框架Otto使用_第1张图片

      上面的按钮与下面的textview不在一个类中,现在的需求是通过点击上面的按钮使下面的textview动态加载数据,用惯了广播的方式,现在我们用otto框架来实现这个效果,开发效率十分的快。写的时候需要导入otto的jar包。

      首先我们建一个BusProvider的类,这个是必须的,为了在类中获取Bus对象,并进行注册。为了让设置UI这样的只能在UI线程中使用的方法在任意线程可以使用,我们使用单例模式建立BusProvider(官方推荐单例方式),并覆写post方法,进行判断如果不是UI线程就通过handler进行发送。

     BusProvider.java

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);
				}
			});
		}
	}
}
    然后我们就能通过单例模式获取bus的对象,并进行注册使用,这次实现的功能是动态传用户名和密码,并在textview中显示,我们需要先写一个中间的bean类

     UserInfo.java

public class UserInfo {

	public String username;
	public String password;

	public UserInfo(String username, String password) {
		this.username = username;
		this.password = password;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

}

   在topfragment中我们通过button的点击事件,进行post事件,并传递username,password两个参数,首先需要获取Bus的对象并进行注册

    topfragment.java

public class TopFragment extends Fragment implements OnClickListener {

	private View view;
	private Button button1;
	private Button button2;
	private Button button3;
	private Button button4;

	private Bus bus;

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		bus = BusProvider.getInstance();
		bus.register(this);
		view = inflater.inflate(R.layout.frag_top, container, false);
		initView();
		initEvent();
		return view;
	}

	private void initEvent() {
		button1.setOnClickListener(this);
		button2.setOnClickListener(this);
		button3.setOnClickListener(this);
		button4.setOnClickListener(this);
	}

	private void initView() {
		button1 = (Button) view.findViewById(R.id.button1);
		button2 = (Button) view.findViewById(R.id.button2);
		button3 = (Button) view.findViewById(R.id.button3);
		button4 = (Button) view.findViewById(R.id.button4);
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.button1:
			bus.post(new UserInfo("admin","admin"));
			break;
		case R.id.button2:
			bus.post(new UserInfo("user","123456"));
			break;
		case R.id.button3:
			bus.post(new UserInfo("32525","abc"));
			break;
		case R.id.button4:
			bus.post(new UserInfo("asdasd","25252"));
			break;

		}
	}
}

 有了事件发送者后,我们在下面的bottomfragment中写一个订阅者方法,首先还是要进行注册bus,然后在方法上加上@Subscribe注解。

bottomfragment.java

public class BottomFragment extends Fragment{
	
	private View view;
	private TextView mTextView;
	private Bus bus;
	
	@Override
	public void onAttach(Activity activity) {
		bus = BusProvider.getInstance();
		bus.register(this);
		super.onAttach(activity);
	}
	
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		view = inflater.inflate(R.layout.frag_bottom, container, false);
		mTextView = (TextView) view.findViewById(R.id.bottom_text);
		return view;
	}

	@Subscribe
	public void setText(UserInfo textstring) {
		String user = textstring.getUsername();
		String psd = textstring.getPassword();
		StringBuffer buffer = new StringBuffer();
		buffer.append("username:").append(user).append(" password:").append(psd);
		mTextView.setText(buffer);
	}
}

  这样就能在按钮点击时动态的加载下面textview的数据。

源码已上传github,地址:https://github.com/sheepm/otto_demo



你可能感兴趣的:(Android学习)