什么是Sticky事件?
關於Sticky事件有的同學可能不是很熟悉,Sticky的意思是粘性的。在Android開 發中,Sticky事件只指事件消費者在事件發布之后才注冊的也能接收到該事件的特殊類型。Android中就有這樣的實例,也就是Sticky Broadcast,即粘性廣播。正常情況下如果發送者發送了某個廣播,而接收者在這個廣播發送后才注冊自己的Receiver,這時接收者便無法接收到 剛才的廣播,為此Android引入了StickyBroadcast,在廣播發送結束后會保存剛剛發送的廣播(Intent),這樣當接收者注冊完 Receiver后就可以接收到剛才已經發布的廣播。這就使得我們可以預先處理一些事件,讓有消費者時再把這些事件投遞給消費者。
AndroidEventBus也提供了這樣的功能,有所不同是AndroidEventBus會存儲所有的Sticky事件,如果某個事件在不需 要再存儲則需要手動進行移除。用戶通過Sticky的形式發布事件,而消費者也需要通過Sticky的形式進行注冊,當然這種注冊除了可以接收 Sticky事件之外和常規的注冊功能是一樣的,其他類型的事件也會被正常處理。發布、接收Sticky事件的步驟有如下幾步 :
1、發布Sticky事件;
EventBus.getDefault().postSticky("hello");
2、 某個時刻訂閱者以Sticky的形式注冊
public class MyReceiver { public MyReceiver() { EventBus.getDefault().registerSticky(this); } @Subscriber private void onStickyEvent(String info) { System.out.println("接收到事件 : " + info); } }
當在某個時刻構造MyReceiver時就會將MyReceiver對象以Sticky的形式注冊到EventBus中,此時先前發布的”hello”事件就會被MyReceiver對象接收到,因此就會執行onStickyEvent
函數,在該函數中實現具體的邏輯即可。當然,不要忘了在某個時刻將MyReceiver注銷,以弱引用的形式持有訂閱者的功能還沒有完成吶!整個過程就這樣結束了~
Sticky事件的運用場景
上文中我們簡單講述了Sticky事件的基本使用步驟,這里我們以一個具體的示例來看看Sticky事件在開發中的使用場景。
在開發過程中,我們經常需要在Activity之間傳值,我們的做法就是將數據塞到Intent中,並且為每個數據設置一個key。當我們傳遞的數 據是一個實體類時,我們的這個類還需要實現序列化接口,比如Parcelable或者Serializable。例如我們需要將一個用戶對象傳遞到用戶個 人信息展示頁面。我們的常規做法是這樣的:
User.java類 :
// 實體類實現序列化 public class User implements Parcelable { String name ; String phoneNum; // 其他字段省略 public User(String aName) { name = aName ; } public User(Parcel in) { super(in); name = in.readString(); phoneNum = in.readString(); } // 代碼省略 @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); dest.writeString(phoneNum); } public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() { @Override public User createFromParcel(Parcel source) { return new User(source); } @Override public User[] newArray(int size) { return new User[size]; } }; }
然后我們要在某個Activity中將這個用戶數據傳遞給個人信息界面ProfileActivity。代碼如下 :
public class MainActivity extends Activity { // 某個點擊事件 @Override public void onClick(View v) { User aUser = new User("Mr.Simple"); aUser.phoneNum = "123456"; // 其他數據 Intent intent = new Intent(this, ProfileActivity.class); intent.putParcelable("user", aUser); startActivity(intent); } }
在某個點擊事件的處理函數中我們通過Intent將數據傳遞給ProfileActivity。我們再看看ProfileActivity從Intent中取出數據的代碼。
public class ProfileActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_profile); // 從Bundle中獲取數據 Bundle extraBundle = getIntent().getExtras(); if (extraBundle != null) { User user = extraBundle.getParcelable("user"); } } }
OK,至此整個過程才算結束了。
大哥,我只是需要傳個數據啊!何苦啊!
這種方式產生了很多的樣板代碼,也讓邏輯變得更復雜,容易出錯。我們再看看使用Sticky事件的實現方式。
User.java類 :
// 實體類實現序列化 public class User { String name ; String phoneNum; // 其他字段省略 public User(String aName) { name = aName ; } // 代碼省略 }
首先User類不需要實現序列化接口,避免了那些樣板代碼。然后在MainActivity中直接將User對象作為Sticky事件發布即可。
public class MainActivity extends Activity { // 某個點擊事件 @Override public void onClick(View v) { User aUser = new User("Mr.Simple"); aUser.phoneNum = "123456"; // 其他數據 // 發布Sticky事件 EventBus.getDefault().postSticky(aUser); // 跳轉到ProfileActivity頁面 Intent intent = new Intent(this, ProfileActivity.class); startActivity(intent); } }
最后我們看看ProfileActivity如何接收數據。
public class ProfileActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_profile); // 以Sticky的形式注冊 EventBus.getDefault().registerSticky(this); } @Subscriber private void onStickyEvent
(User info){ // 這里實現你的邏輯即可, info即為傳遞過來的User對象 } }
在ProfileActivity中我們將ProfileActivity自身作為訂閱者注冊到總線當中,此時ProfileActivity就會 接收到上面發布的Sticky事件,這個事件對象就是User對象。此時就會觸發ProfileActivity 中的receiveUser函數,info參數就是Sticky事件的那個用戶信息對象,在receiveUser中實現自己的邏輯即可。
是的!我們並沒有在onDestory中對訂閱者進行注銷,也就是沒有調用EventBus的unregister()函數,這就是最新版的特性之一,也是目前唯一不需要手動注銷的事件總線庫。
借鑒:http://blog.csdn.net/bboyfeiyu/article/details/46116357