主要改變的就是HandlerFactory和RXBus這兩個類,又加了幾個方法,這一次使用到了反射。java
其餘的類沒有改變,在上一篇文章中均可以找到源碼。android
新的RxBus以下所示(仍是基於網上其餘人的改的):數組
package com.mitnick.root.mycample.util.rxbus; import android.util.Log; import com.mitnick.root.mycample.util.rxbus.responslink.ResponseNode; import rx.Observable; import rx.Subscription; import rx.functions.Action1; import rx.functions.Func1; import rx.subjects.PublishSubject; import rx.subjects.SerializedSubject; import rx.subjects.Subject; /** * Created by root on 16-4-12. * 事件體只會被髮射到相對應的主題的訂閱者 */ public class RxBus { private static volatile RxBus defaultInstance; // 主題 private final Subject bus; public RxBus() { bus = new SerializedSubject<>(PublishSubject.create()); } // 單例RxBus public static RxBus getDefault() { RxBus rxBus = defaultInstance; if (defaultInstance == null) { synchronized (RxBus.class) { rxBus = defaultInstance; if (defaultInstance == null) { rxBus = new RxBus(); defaultInstance = rxBus; } } } return rxBus; } /** * 事件總線發射一個事件 * @Param rxBusEvent : 事件體 * */ public void post (RxBusEvent rxBusEvent) { bus.onNext(rxBusEvent); } /** * 訂閱事件總線的某一個主題 * @Param tag : 訂閱的主題,事件總線只會對感興趣的主題發射事件 * @Param eventType : 根據傳遞的 eventType 類型返回特定類型(eventType)的 被觀察者 * */ public <T> Observable<T> toObserverable (Class<T> eventType) { return bus.ofType(eventType); // 這裏感謝小鄧子的提醒: ofType = filter + cast // return bus.filter(new Func1<Object, Boolean>() { // @Override // public Boolean call(Object o) { // return eventType.isInstance(o); // } // }) .cast(eventType); } public static Subscription subscription(final String[] tags, final ResponseNode responseNode){ return getDefault().toObserverable(RxBusEvent.class) .filter(new Func1<RxBusEvent, Boolean>() { @Override public Boolean call(RxBusEvent rxBusEvent) { for(String tag : tags){ if(rxBusEvent.getTag().equals(tag)){ return true; } } return false; } }) .subscribe(new Action1<RxBusEvent>() { @Override public void call(final RxBusEvent rxBusEvent) { responseNode.operator(rxBusEvent);//開啓職責鏈處理事件 } }, new Action1<Throwable>() { @Override public void call(Throwable throwable) { // TODO: 處理異常 Log.e("事件總線",throwable.toString()); } }); } }
新的HandlerFactory以下所示:app
package com.mitnick.root.mycample.util.rxbus.responslink; import android.content.Context; import android.util.Log; import java.lang.reflect.Method; import java.util.Map; /** * Created by root on 16-5-17. */ public class HandlerFactory { /** * 獲得一個空的職責鏈處理節點 * @return responseNode 一個空的職責鏈處理節點 * */ public static ResponseNode getHandler(){ return new ResponseNode(new DoSomthing(null) { @Override public boolean dosomthing() { return false; } }); } /** * @param c 用於反射方法 * @param context 傳入一個Activity用於回調方法 * @param events 須要分開處理的事件名稱 * @return responseNode * * */ public static ResponseNode getHandler(final Class<?> c, final Context context, String[] events){ ResponseNode responseNode = getHandler(); ResponseNode buffer = responseNode; for(final String event : events){ buffer = buffer.setHandler(new ResponseNode(new DoSomthing(event) { @Override public boolean dosomthing() { try { Method method = c.getMethod(event); method.invoke(context); context.getClass().getMethod(event); } catch (Exception e) { e.printStackTrace(); Log.e("HandlerFactory",e.toString()); return filter(); } return filter(); } })); } buffer.setHandler(responseNode);//循環職責鏈 return responseNode; } /** * @param context 傳入一個Activity用於回調方法 * @param events 須要分開處理的事件名稱 * @return responseNode * * */ public static ResponseNode getHandler(final Context context, String[] events){ ResponseNode responseNode = getHandler(); ResponseNode buffer = responseNode; for(final String event : events){ buffer = buffer.setHandler(new ResponseNode(new DoSomthing(event) { @Override public boolean dosomthing() { try { Method method = context.getClass().getMethod(event); method.invoke(context); } catch (Exception e) { e.printStackTrace(); Log.e("HandlerFactory",e.toString()); return filter(); } return filter(); } })); } buffer.setHandler(responseNode);//循環職責鏈 return responseNode; } /** * @param context 傳入一個Activity用於回調方法 * @param events 須要分開處理的事件名稱 * @param eventMap 事件名稱的一個轉換,總線消息發送者無需知道接受者要回調哪一個函數來實現 * @return responseNode * */ public static ResponseNode getHandler(final Context context, String[] events, final Map<String, String> eventMap){ ResponseNode responseNode = getHandler(); ResponseNode buffer = responseNode; for(final String event : events){ buffer = buffer.setHandler(new ResponseNode(new DoSomthing(event) { @Override public boolean dosomthing() { try { String buffer = event; if(eventMap.containsKey(event)){ buffer = eventMap.get(event); } Method method = context.getClass().getMethod(buffer); method.invoke(context); } catch (Exception e) { e.printStackTrace(); Log.e("HandlerFactory",e.toString()); return filter(); } return filter(); } })); } buffer.setHandler(responseNode);//循環職責鏈 return responseNode; } }
下面來看一下如何註冊事件:ide
//訂閱事件總線並使用職責鏈處理 HashMap<String,String> reflact = new HashMap<>(); reflact.put("one","loginSuccess"); rxSubscription = RxBus.subscription( new String[]{"loginModel"}, HandlerFactory.getHandler( this, new String[]{"one", "loginFailed"}, reflact ) );
對,就是如此的簡單!函數
基本原理是這樣的,經過HandlerFactory得到職責鏈處理節點。HandlerFactory.getHandler的第一個參數是this,反射的回調須要用到this。第二個參數是一個String數組,這個數組的每個元素就是每個感興趣的事件(能夠有多個事件哦)。第三個參數是一個Map,是這樣考慮的:由於我要實現高度的解耦,因此Model發送的每個事件都不會知道將會由誰來處理,可是在事件接受方須要將每個事件的每個動做(event)來經過反射映射到相應的處理函數(固然這一切都已經被HandlerFactory封裝好了),因此須要用到這個Map來作一下映射,固然,若是event與處理函數同名,那麼就只須要使用它的只有前兩個參數的重載函數就能夠了。post
固然,它也能夠同時觀察多個事件源,RxBus.subscription的第一個參數是一個String數組,它就是來存放事件源的。測試
下面再來看一下如何發送事件:this
RxBus.getDefault().post(new RxBusEvent("loginModel","one",null));
發送事件也是如此的簡單!spa
下面來看一個具體的實現:
package com.mitnick.root.mycample; import android.app.ActivityOptions; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.transition.Explode; import android.view.View; import android.view.Window; import android.widget.Button; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.mitnick.root.mycample.bean.user.User; import com.mitnick.root.mycample.util.rxbus.RxBus; import com.mitnick.root.mycample.util.rxbus.RxBusEvent; import com.mitnick.root.mycample.util.rxbus.responslink.HandlerFactory; import java.util.HashMap; import butterknife.Bind; import butterknife.ButterKnife; import me.james.biuedittext.BiuEditText; import rx.Subscription; public class LoginActivity extends AppCompatActivity implements View.OnClickListener { @Bind(R.id.userName) BiuEditText userName; @Bind(R.id.userPsw) BiuEditText userPsw; @Bind(R.id.login) Button login; @Bind(R.id.verify) TextView verify; @Bind(R.id.imageView3) ImageView baidu; @Bind(R.id.imageView2) ImageView weixin; @Bind(R.id.imageView) ImageView qq; @Bind(R.id.progressBar4) ProgressBar progress; private Subscription rxSubscription = null;//訂閱RxBus事件 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 容許使用transitions getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); setContentView(R.layout.activity_login); ButterKnife.bind(this); } private void init() { setTitle("登陸"); login.setOnClickListener(this); verify.setOnClickListener(this); qq.setOnClickListener(this); weixin.setOnClickListener(this); baidu.setOnClickListener(this); // 設置一個exit transition getWindow().setExitTransition(new Explode());//new Slide() new Fade() //訂閱事件總線並使用職責鏈處理 HashMap<String,String> reflact = new HashMap<>(); reflact.put("one","loginSuccess"); rxSubscription = RxBus.subscription( new String[]{"loginModel"}, HandlerFactory.getHandler( this, new String[]{"one", "loginFailed"}, reflact ) ); RxBus.getDefault().post(new RxBusEvent("loginModel","one",null)); } @Override protected void onResume() { super.onResume(); if(User.getInstence(null,null).isLogin()){ finish(); } init(); } @Override protected void onPause() { if(!rxSubscription.isUnsubscribed()){ rxSubscription.unsubscribe(); } super.onPause(); } @Override protected void onDestroy() { ButterKnife.unbind(this); super.onDestroy(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.login: login.setText(""); progress.setVisibility(View.VISIBLE); break; case R.id.imageView: break; case R.id.imageView2: break; case R.id.imageView3: break; } } public void loginSuccess(){ User.getInstence(userName.getText().toString(),userPsw.getText().toString()); startActivity(new Intent(LoginActivity.this, MainActivity.class), ActivityOptions.makeSceneTransitionAnimation(this).toBundle()); } public void loginFailed(){ login.setText("登陸"); progress.setVisibility(View.INVISIBLE); } }
在這個具體實現樣例代碼中,由於爲了測試,我就在訂閱了事件總線以後馬上又本身向事件總線發送了一條事件。loginSuccess函數和loginFailed函數就是經過反射機制來回調的。