Otto是一個在Android中的事件匯流排框架,它是square的一個開源框架,具體介紹點選這裡,專案下載點選這裡
為什麼要使用Otto事件匯流排:
通常來說在Android中:
1、Activity與Activity間的傳值是通過Intent
,值回撥是通過startActivityForResult()
2、Activity與Fragment間的傳值是通過setArguments
,值回撥是通過實現onAttach()
的Interface方式
3、而Fragment與Fragment間的互動則應該是通過它們關聯的Activity作為中間鍵來互動
4、包括Activity與Service的互動,可能眾多同學會採用Binder機制來處理,而其實Binder機制本質也是通過介面回撥方式來進行值回撥的
5、或者在更復雜的應用場景下,比如:ActivityA跳轉到ActivityB,ActivityB跳轉到ActivityC,此時需要從ActivityC中獲取到使用者的運算元據返回到ActivityA和ActivityB中顯示,或者在Activity中有多個Fragment,其中一個Fragment裡的資料變化需要同步更新其它Fragment的資料變化,這時候如果使用Interface的方式進行它們間的互動則比較複雜,耦合度也高
所以,針對上面這些問題,大多數在處理值互動的問題上類之間都是耦合在一起的,而Otto事件匯流排框架就是降低各個類間的耦合度的。
Otto事件匯流排
Otto中真正用到的就只有一個類兩個註解三個方法:
Bus
– 管理註冊、登出和釋出事件@Produce
– 標記該方法是生產者,產生的事件內容為該方法的返回值@Subscribe
– 標記該方法是訂閱者,表示訂閱了一個事件,方法需要修飾符為public,而區分不同的訂閱者是通過方法的引數來區分的,且訂閱了某事件的所有訂閱者都可以收到該事件register(Object obj)
– 註冊,訂閱事件前都需要註冊unregister(Object obj)
– 登出,放棄之前所有事件的訂閱post(Object event)
– 釋出一個事件,這個事件會被所有標記了@Subscribe註解的方法獲得
使用Otto事件匯流排
首先新增依賴:
1 2 3 |
dependencies { compile 'com.squareup:otto:+' } |
1、為了避免重複建立Bus物件,我們先為Bus建立一個單例物件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class BusProvider { private volatile static Bus bus = null; private BusProvider() { } public static Bus getInstance() { if (bus == null) { synchronized (BusProvider.class) { bus = new Bus(); } } return bus; } } |
2、建立一個Bean,用來傳遞各類間的資料
1 2 3 4 5 6 7 8 9 10 11 |
public class EventData { private String content; public String getContent() { return content; } public void setContent(String content) { this.content = content; } } |
3、在MainActivity中註冊並且建立訂閱者訂閱資料
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); BusProvider.getInstance().register(this);//訂閱事件 Button mButton = (Button) findViewById(R.id.btn); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { TestActivity.jumpToTestActivity(MainActivity.this); } }); } @Subscribe public void subscribeEvent(EventData data){ Log.v("zxy", data.getContent()); } @Override protected void onDestroy() { super.onDestroy(); BusProvider.getInstance().unregister(this);//登出訂閱 } public static void jumpToMainActivity(Context context){ context.startActivity(new Intent(context,MainActivity.class)); } } |
4、在TestActivity中釋出事件
釋出事件有兩種方法:
1、使用@Produce
註解來生產事件,不過它生產事件前它需要註冊、生產完事件後需要登出,如果使用這種方法則在跳轉到生產者所在的類中則會立即產生事件觸發訂閱者,即在MainActivity跳轉到TestActivity時,會立即產生事件並訂閱了該事件的方法會收到該事件,如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
public class TestActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); BusProvider.getInstance().register(this); } @Produce public EventData produceEvent(){ EventData mEventData = new EventData(); mEventData.setContent("hello word!"); return mEventData; } @Override protected void onDestroy() { super.onDestroy(); BusProvider.getInstance().unregister(this); } public static void jumpToTestActivity(Context context){ context.startActivity(new Intent(context, TestActivity.class)); } } |
則在MainActivity跳轉到TestActivity時訂閱者會馬上收到事件,輸出的Log資訊為:
1 |
09-06 03:46:16.738 5958-5958/? V/zxy﹕ hello word! |
2、通過post()來發布事件,它不需要註冊和登出,而且它不會在介面跳轉時馬上釋出事件,而是我們人為的控制該事件什麼時候釋出,使用如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class TestActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); } public void click(View view){ EventData mEventData = new EventData(); mEventData.setContent("hello word!"); BusProvider.getInstance().post(mEventData);//釋出事件 MainActivity.jumpToMainActivity(this); } public static void jumpToTestActivity(Context context){ context.startActivity(new Intent(context, TestActivity.class)); } } |
當我們點選按鈕時候,這個事件就釋出出去了,而訂閱了該事件的方法就會收到,列印的Log為:
1 |
09-06 03:46:18.738 5958-5958/? V/zxy﹕ hello word! |
【注】:釋出事件需要釋出的是一個Object物件,而且這個物件不能為null,所以在資料量大的時候我們可以建立個Bean類,而傳當個資料時候如字串等則直接傳String就好。
可以看到通過Otto事件匯流排來處理類與類之間的互動,可以使得我們的程式碼更容易理解,類與類之間也解耦了。
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!
任選一種支付方式