廣播,在咱們的應用中起着一個很是重要的角色。就好比說咱們常用的Intent
、IntentFilter
,就有着廣播的做用。java
在個人Android工具包項目中就集成了網絡廣播的動態註冊。android
由於沒有直接的圖示能夠上,並且Broadcast中並無onCreate
、onDestroy
這樣方法,只能經過官方文檔驗證。 git
Activity
中的具體操做相關。
在Android 8.0之後已經不在支持靜態廣播了github
public class NetworkReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION) && App.getInstance() != null) {
App.getInstance().notifyObservers(isNetConnected(context));
}
}
}
複製代碼
雖然是兩種廣播形式,可是他們一樣要幹一件事情,就是繼承BroadcastReceiver
,並重寫onReceive()
方法。安全
這個廣播一樣可使用在應用內,可是這種廣播的安全性有待質疑。網絡
// 消息傳遞
sendBroadcast(Intent);
複製代碼
<receiver android:name="com.clericyi.basehelper.network.NetworkReceiver">
<intent-filter>
<action android:name="android.intent.action.BATTERY_LOW"/>
</intent-filter>
</receiver>
複製代碼
和靜態廣播不一樣的地方,動態廣播註冊完之後須要進行註銷操做。異步
// 註冊
networkReceiver = new NetworkReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(networkReceiver, intentFilter);
// 註銷(若是沒有註銷,將會發生內存泄漏)
unregisterReceiver(networkReceiver);
複製代碼
//註冊
networkReceiver = new NetworkReceiver();
localBroadcastManager = LocalBroadcastManager.getInstance(this); // --> 以單例模式進行建立
localBroadcastManager.registerReceiver(networkReceiver, new IntentFilter("須要去過濾的信息"));
// 發送消息
localBroadcastManager.sendBroadcast(Intent);
// 註銷
localBroadcastManager.unregisterReceiver(networkReceiver);
複製代碼
爲何要導讀LocalBroadcastManager
源碼呢?ide
實際上是想讓讀者們知道LocalBroadcastManager
使用並非Binder
機制來完成通訊的。函數
public static LocalBroadcastManager getInstance(@NonNull Context context) {
synchronized (mLock) {
if (mInstance == null) {
mInstance = new LocalBroadcastManager(context.getApplicationContext()); // 1 -->
}
return mInstance;
}
}
// 由註釋1直接調用的方法
private LocalBroadcastManager(Context context) {
mAppContext = context;
mHandler = new Handler(context.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_EXEC_PENDING_BROADCASTS:
executePendingBroadcasts();
break;
default:
super.handleMessage(msg);
}
}
};
}
複製代碼
那這裏就是很清楚的知道,這是一個以DCL
的方式,來直接完成對單例的建立,而在構造函數中,定義了一個Handler
。工具
那咱們就來作一個猜想,咱們在應用內的廣播本質實際上是基於一個Handler
的一異步傳輸機制。爲了驗證!!咱們就須要去了解他的sendBroadcast(Intent)
方法。
public boolean sendBroadcast(@NonNull Intent intent) {
synchronized (mReceivers) {
// 拿到傳遞過來的Intent中保存的數據
final String action = intent.getAction();
final String type = intent.resolveTypeIfNeeded(
mAppContext.getContentResolver());
final Uri data = intent.getData();
final String scheme = intent.getScheme();
final Set<String> categories = intent.getCategories();
// 。。。。。
// 獲取配置的Action
ArrayList<ReceiverRecord> entries = mActions.get(intent.getAction());
if (entries != null) {
if (debug) Log.v(TAG, "Action list: " + entries);
ArrayList<ReceiverRecord> receivers = null;
// 。。。。。 對變量receivers的一些列操做。
// 存在接受對象時,將數據經過Handler的方式傳遞出去。
if (receivers != null) {
for (int i=0; i<receivers.size(); i++) {
receivers.get(i).broadcasting = false;
}
mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));
if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {
mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);
}
return true;
}
}
}
return false;
}
複製代碼
經過代碼已經成功驗證了,其實LocalBroadcast
最終基於的數據傳輸機制就是咱們的Handler
,這就是和應用間廣播最大的不一樣之處了。
ANR
的慘狀,廣播的耗時操做時長不容許超過10s。並且廣播內通常也不會像Service
和Activity
同樣會使用Thread
來完成咱們的耗時操做。LocalBroadcast
)使用的Handler
的消息傳輸機制;應用間廣播或者說是進程間廣播(Broadcast
)使用的則是Binder
的機制。以上就是個人學習成果,若是有什麼我沒有思考到的地方或是文章內存在錯誤,歡迎與我分享。
相關文章推薦: