Android 你需要掌握的知識(shí)(二)

目錄

Service.png

Broadcast Receiver.png

一.Service詳解

一.Service基礎(chǔ)

1.什么是Service

Service是Android中實(shí)現(xiàn)程序后臺(tái)運(yùn)行的解決方案,是一個(gè)可以在后臺(tái)執(zhí)行長(zhǎng)時(shí)間運(yùn)行操作而沒(méi)有用戶(hù)界面的應(yīng)用組件
Service可由其他應(yīng)用(如:Activity,Broadcast)組件啟動(dòng),服務(wù)在啟動(dòng)后會(huì)一直在后臺(tái)運(yùn)行。即使啟動(dòng)它的Activity或Broadcast已經(jīng)被銷(xiāo)毀也不會(huì)受影響,另外也可以把Service綁定到Activity,可以讓Service和Activity之間進(jìn)行數(shù)據(jù)交互,甚至Service和Activity有可能在不同的進(jìn)程中也可以用進(jìn)程間通信來(lái)進(jìn)行數(shù)據(jù)傳輸。
注意:Service(服務(wù))和Broadcast(廣播)有一個(gè)共同點(diǎn)。它們都是運(yùn)行在主線程當(dāng)中,不能耗時(shí)操作。

2.Service和Thread的區(qū)別

1.Thread是程序執(zhí)行的最小單元,線程,可以用它來(lái)執(zhí)行一些異步操作
Service是安卓的一種機(jī)制,當(dāng)它運(yùn)行的時(shí)候,如果是本地的Service,那么它對(duì)應(yīng)的Service是運(yùn)行在主線程上的。

2.Thread 運(yùn)行是相對(duì)獨(dú)立的,而Service運(yùn)行是依賴(lài)于創(chuàng)建服務(wù)時(shí)所在的應(yīng)用程序進(jìn)程。

服務(wù)和后臺(tái)是兩個(gè)概念,android 的后臺(tái)指的是它的運(yùn)行完全不依賴(lài)于UI線程,即使Activity被銷(xiāo)毀了,或者程序被關(guān)閉了,這個(gè)服務(wù)進(jìn)程仍然存在,會(huì)在后臺(tái)進(jìn)行一些如:計(jì)算,數(shù)據(jù)統(tǒng)計(jì)等。Service仍然可以繼續(xù)運(yùn)作,如果要Service做耗時(shí)操作,依舊要在Service中創(chuàng)建子線程。在里面做耗時(shí)邏輯。

Activity中創(chuàng)建子線程和Service中創(chuàng)建子線程的不同就是,Activity中很難對(duì)子線程控制,Activity在被銷(xiāo)毀后就無(wú)法獲取之前的子線程實(shí)例。
如果在Service中就可以很放心的銷(xiāo)毀Activity,不用擔(dān)心無(wú)法控制的情況。

二.開(kāi)啟Service的兩種方式和區(qū)別

1.startService

1.定義一個(gè)類(lèi)繼承Service

public class MyService extends Service 

2.在AndroidManifest.xml中配置該service

<application...
        <service android:name=".MyService"></service>
    </application>

3.使用Context的startService(startIntent)方法啟動(dòng)該Service

Intent startIntent = new Intent(this,MyService.class);
startService(startIntent);

4.不在使用時(shí)調(diào)用stopService(stopIntent)方法停止該服務(wù)。

Intent stopIntent = new Intent(this,MyService.class);
stopService(stopIntent);

MyService 繼承 Service
服務(wù)啟動(dòng)后,會(huì)先調(diào)用MyService中的onCreate()的方法。

  /**
     * 首次創(chuàng)建服務(wù)時(shí),系統(tǒng)會(huì)調(diào)用此方法來(lái)執(zhí)行一次性設(shè)置程序(在調(diào)用onStartCommand()或onBind()之前)
     * 如果服務(wù)已在運(yùn)行,則不會(huì)調(diào)用此方法,該方法只被調(diào)用一次
     */
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate() executed");
    }

在用startService啟動(dòng)這個(gè)服務(wù)時(shí),就會(huì)調(diào)用onStartCommand方法,一旦調(diào)用這個(gè)方法,這個(gè)服務(wù)就會(huì)被正式開(kāi)啟??梢栽谶@個(gè)方法中做自己的操作。

  /**
   * 每次通過(guò)startService方法啟動(dòng)Service時(shí)都會(huì)被回調(diào)
   */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand() executed");
        return super.onStartCommand(intent, flags, startId);
    }

在onStartCommand方法中有一個(gè)返回值是int,源碼中是這樣:

public @StartResult int onStartCommand(Intent intent, @StartArgFlags int flags, int startId) {
        onStart(intent, startId);
        return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
    }

如果onStartCommand方法返回的是START_STICKY,意味著當(dāng)整個(gè)Service因?yàn)閮?nèi)存不足而被系統(tǒng)殺掉的之后,一段時(shí)間內(nèi)存再度空閑的時(shí)候,系統(tǒng)會(huì)嘗試重新創(chuàng)建這個(gè)Service,創(chuàng)建成功后,又會(huì)調(diào)用onStartCommand方法,但其中的intent是空,這個(gè)值適合循環(huán)播放,天氣預(yù)報(bào)這種服務(wù)。

當(dāng)服務(wù)不在被使用的時(shí)候調(diào)用onDestroy()方法,Service可以在這個(gè)方法里面進(jìn)行一些資源的清理(線程,注冊(cè)的監(jiān)聽(tīng)器,Content Provider),會(huì)進(jìn)行回收。

/**
     * 服務(wù)銷(xiāo)毀時(shí)的回調(diào)
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy() executed");
    }
2.bindService

bindService意味著在綁定服務(wù)的時(shí)候,服務(wù)和Activity已經(jīng)處于綁定狀態(tài),綁定服務(wù)提供了一個(gè)客戶(hù)端和服務(wù)端的接口,相當(dāng)于Activity和Service交互的接口,它允許Activity和Service進(jìn)行數(shù)據(jù)交互,發(fā)出請(qǐng)求獲取結(jié)果等等。甚至如果Activity和Service在不同進(jìn)程當(dāng)中的時(shí)候,可以進(jìn)行進(jìn)程間通信來(lái)傳輸數(shù)據(jù),這僅僅是在Activity和Service綁定之后才能運(yùn)行,同時(shí)多個(gè)Activity可以綁定一個(gè)Service,但是綁定取消后,這個(gè)服務(wù)就會(huì)自動(dòng)被銷(xiāo)毀,并不像startService一樣必須要調(diào)用stopService才能被銷(xiāo)毀

bindService啟動(dòng)的方式:
1.創(chuàng)建Service,繼承自Service并在類(lèi)中,創(chuàng)建一個(gè)實(shí)現(xiàn)IBinder接口的實(shí)例對(duì)象并提供公共方法給Activity調(diào)用
2.從 onBind()回調(diào)方法返回此Binder實(shí)例。
3.Activity,從onServiceConnected()回調(diào)方法接收Binder,并使用提供的方法調(diào)用綁定服務(wù)。

和startService不同的是,它在MyService中實(shí)現(xiàn)了一個(gè)Binder的內(nèi)部類(lèi)

  /**
     * 創(chuàng)建Binder對(duì)象,返回給Activity使用,提供數(shù)據(jù)交換的接口
     */
    class DownloadBinder extends Binder {
        //聲明一個(gè)方法 getService (提供給Activity調(diào)用)
        MyService getService() {
            //返回當(dāng)前對(duì)象,這樣就可以在Activice 中調(diào)用Service的公共方法
            return MyService.this;
        }

    }

值得注意的是和startService不同的是,在onBind方法中它返回了一個(gè)Binder,這個(gè)downloadBinder是我們自己創(chuàng)建的

private DownloadBinder downloadBinder = new DownloadBinder();
    @Override
    public IBinder onBind(Intent intent) {
        return downloadBinder;
    }

在Activity中我們要?jiǎng)?chuàng)建一個(gè)ServiceConnection的類(lèi),它代表的是Activity和Service的連接。

 private MyService.DownloadBinder downloadBinder;
    /**
     * ServiceConnection代表與服務(wù)的鏈接,它只有兩個(gè)方法。
     * onServiceConnected和onServiceDisconnected
     * 前者是在操作者在連接一個(gè)服務(wù)成功時(shí)被調(diào)用,而后者是在服務(wù)崩潰或者殺死導(dǎo)致的連接中斷時(shí)被調(diào)用
     */
    private ServiceConnection connection = new ServiceConnection() {
        /**
         *  與服務(wù)端交互的接口方法,綁定服務(wù)的時(shí)候被回調(diào),在這個(gè)方法獲取綁定Service傳遞過(guò)來(lái)的IBinder對(duì)象
         *  通過(guò)這個(gè)IBinder對(duì)象,實(shí)現(xiàn)Activity和Service交互
         */
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            downloadBinder = (MyService.DownloadBinder) service;
            downloadBinder.getService().getCount();
        }
        /**
         * 取消綁定的時(shí)候被回調(diào),但正常情況下是不被調(diào)用的,它的調(diào)用時(shí)機(jī)是當(dāng)Service服務(wù)被意外摧毀時(shí)
         * 如內(nèi)存資源不足時(shí)這個(gè)方法被自動(dòng)調(diào)用
         */

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

通過(guò)bindService(Intent service, ServiceConnection conn, int flags)方法,來(lái)啟動(dòng)Service

Intent startIntent = new Intent(this, MyService.class);
bindService(startIntent,connection,BIND_AUTO_CREATE);

通過(guò)unbindService(ServiceConnection conn) 方法來(lái)停止Service

unbindService(connection);

二.Broadcast Receiver詳解

一.廣播

1.廣播的定義

廣播是一種廣泛運(yùn)用的在應(yīng)用程序之間傳輸信息的機(jī)制,廣播使用了設(shè)計(jì)模式中的觀察者模式,當(dāng)被觀察者數(shù)據(jù)變換時(shí)會(huì)通知觀察者做相應(yīng)的數(shù)據(jù)處理,android中要發(fā)送的廣播內(nèi)容是一個(gè)Intent。在這個(gè)Intent里可以攜帶一些我們要傳送的數(shù)據(jù)。
要記住這兩點(diǎn)
1.廣播實(shí)現(xiàn)了不同程序之間的數(shù)據(jù)傳輸與共享,只要和發(fā)送廣播的Action相同的接收者都能接收這個(gè)廣播,就是發(fā)送一個(gè)廣播可以被很多廣播Receive所接受,典型的就是系統(tǒng)應(yīng)用(短信,電話(huà)等通知)。只要我們實(shí)現(xiàn)了他們Action的Broadcast Receiver,就能接收他們的數(shù)據(jù)。
2.廣播接收者還有一個(gè)通知的作用,比如在服務(wù)中可以發(fā)送程序給Activity,讓它更新UI,我們知道Service是沒(méi)有界面的,它是在后臺(tái)運(yùn)行的一個(gè)組件,所以這時(shí)候我們就可以通過(guò)廣播接收者專(zhuān)門(mén)接收從Service發(fā)過(guò)來(lái)的數(shù)據(jù)和通知,而不要讓Service直接和Activity進(jìn)行交互了。

2.廣播的場(chǎng)景

1.同意app內(nèi)在具有多個(gè)進(jìn)程的不同組件之間的消息通信(在一個(gè)app內(nèi)會(huì)開(kāi)啟多個(gè)進(jìn)程,比如app中會(huì)有定位進(jìn)程,主進(jìn)程,兩個(gè)進(jìn)程之間的通信就可以用到廣播)
2.不同app之間的組件之間的消息通信(兩個(gè)app間通過(guò)廣播來(lái)傳遞對(duì)方的消息,比如一個(gè)公司的多個(gè)app進(jìn)行推廣,就會(huì)用到通知)

3.廣播的種類(lèi)

1)Normal Broadcast(普通廣播) : 會(huì)調(diào)用Content.sendBroadcast這個(gè)方法進(jìn)行處理
2)System Broadcast(系統(tǒng)廣播,有序廣播):會(huì)調(diào)用Content.sendOrderedBroadcast這個(gè)方法進(jìn)行處理
3)Local Broadcast(本地廣播):只在APP內(nèi)傳播

二.實(shí)現(xiàn)廣播-receiver

1.靜態(tài)注冊(cè):注冊(cè)完成就一直運(yùn)行。

直接把廣播接收者寫(xiě)在AndroidManifest.xml文件中。特點(diǎn),它所依賴(lài)的Activity銷(xiāo)毀了,但是仍然能夠接收廣播,甚至把進(jìn)程殺死,仍然能接收廣播,但是和動(dòng)態(tài)注冊(cè)相比,還是不是太靈活。

2.動(dòng)態(tài)注冊(cè):跟隨activity生命周期。

在代碼中通過(guò)調(diào)用Context的registerReceiver()方法進(jìn)行動(dòng)態(tài)注冊(cè)BroadcastReceiver,要記住動(dòng)態(tài)廣播最好在Activity的onResume()注冊(cè)、onPause()注銷(xiāo),否則會(huì)導(dǎo)致內(nèi)存泄露。同時(shí)動(dòng)態(tài)注冊(cè)還有這個(gè)特點(diǎn),它的生命周期是跟隨activity生命周期,所以當(dāng)activity生命周期銷(xiāo)毀時(shí),這個(gè)動(dòng)態(tài)注冊(cè)的廣播接收者也就失效了。

三.內(nèi)部實(shí)現(xiàn)機(jī)制

1.自定義廣播接收者BroadcastReceiver,并復(fù)寫(xiě)onRecvice()方法;

2.通過(guò)Binder機(jī)制向AMS(Activity Manager Service)進(jìn)行注冊(cè);
AMS(Activity Manager Service):是貫穿android系統(tǒng)組件的一個(gè)核心服務(wù),負(fù)責(zé)啟動(dòng)四大組件的啟動(dòng),切換,調(diào)度以及應(yīng)用程序的調(diào)度和管理工作。所以AMS是負(fù)責(zé)BroadcastReceiver的創(chuàng)建。
Biner機(jī)制:是android進(jìn)程間通信的一個(gè)核心,它的整體設(shè)計(jì)架構(gòu)是客戶(hù)端/服務(wù)端結(jié)構(gòu),C/S結(jié)構(gòu),客戶(hù)端進(jìn)程可以獲取到服務(wù)端進(jìn)程的代理,并通過(guò)這個(gè)代理接口,通過(guò)方法來(lái)讀取數(shù)據(jù),來(lái)完成進(jìn)程間的數(shù)據(jù)通信。

3.廣播發(fā)送者通過(guò)Binder機(jī)制向ASM發(fā)送廣播

4.ASM查找符合相應(yīng)條件(IntentFilter / Permission等)的BroadcastReceiver,將廣播發(fā)送到BroadcastReceiver(一般情況下是Activity)相應(yīng)的消息循環(huán)隊(duì)列中

5.消息循環(huán)執(zhí)行拿到此廣播,回調(diào)BroadcastReceiver中的onReceive()方法。

四.LocalBroadcastManager詳解(參考文章

1.使用它發(fā)送廣播將只在自身App內(nèi)傳播,因此不必?fù)?dān)心泄露隱私數(shù)據(jù)
2.其他App無(wú)法對(duì)你的App發(fā)送該廣播,因?yàn)槟愕腁pp根本就不可能接受到非自身應(yīng)用發(fā)送的該廣播,因此你不必?fù)?dān)心有安全漏洞可以利用。
3.比系統(tǒng)的全局廣播更加高效。

還要強(qiáng)調(diào),安全漏洞隱私數(shù)據(jù)

1.如果不是本地廣播,代碼被反編譯后,知道了你的Action,那么第三方應(yīng)用就能發(fā)送與該Action匹配的廣播,而你的應(yīng)用也可以接收到,這樣第三方應(yīng)用就可以用你的廣播做很多事情,(分享鏈接,植入廣告)。
2.如果被別人知道了你應(yīng)用的Action,當(dāng)你使用廣播來(lái)傳遞數(shù)據(jù)時(shí),別的應(yīng)用也能接收到你的廣播,通過(guò)Action匹配,就能獲取你的私密數(shù)據(jù)(用戶(hù)數(shù)據(jù),發(fā)送惡意信息等)

看一下LocalBroadcastManager的源碼
先看一下它的構(gòu)造方法:

  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);
                }
            }
        };
    }

它內(nèi)部是由單例實(shí)現(xiàn)的而私有化構(gòu)造函數(shù),它內(nèi)部是一個(gè)Handler對(duì)象,對(duì)象傳入的是getMainLooper(),它是主線程,它代表它是在主線程運(yùn)作的Looper。
再看一下它里邊3個(gè)比較重要的集合類(lèi)

    private final HashMap<BroadcastReceiver, ArrayList<IntentFilter>> mReceivers
            = new HashMap<BroadcastReceiver, ArrayList<IntentFilter>>();
    private final HashMap<String, ArrayList<ReceiverRecord>> mActions
            = new HashMap<String, ArrayList<ReceiverRecord>>();

    private final ArrayList<BroadcastRecord> mPendingBroadcasts
            = new ArrayList<BroadcastRecord>();

mReceivers可以看到是一個(gè)HashMap類(lèi),它里面的key是BroadcastReceiver,value是ArrayList,ArrayList里面的數(shù)據(jù)是IntentFilter,IntentFilter是一個(gè)過(guò)濾類(lèi),它會(huì)過(guò)濾我們的廣播,為什么是一個(gè)集合呢,因?yàn)閺V播接收器可以接收到不同Action的廣播,所以它這里就一定要維護(hù)一張表,一個(gè)BroadcastReceiver和一個(gè)Action是一一對(duì)應(yīng)的。
mActions也是一個(gè)HashMap類(lèi),它的key 就是一個(gè)Action,它的value是ArrayList,ArrayList里面的數(shù)據(jù)是ReceiverRecord,它這個(gè)集合維護(hù)著Action所對(duì)應(yīng)的ReceiverRecord,一一對(duì)應(yīng)的一個(gè)HashMap表。
mPendingBroadcasts是一個(gè)ArrayList集合,它存儲(chǔ)的就是BroadcastRecord對(duì)象。

    private static class BroadcastRecord {
        final Intent intent;
        final ArrayList<ReceiverRecord> receivers;

        BroadcastRecord(Intent _intent, ArrayList<ReceiverRecord> _receivers) {
            intent = _intent;
            receivers = _receivers;
        }
    }

而B(niǎo)roadcastRecord對(duì)象它存儲(chǔ)的是一個(gè)intent和receivers,所以說(shuō)mPendingBroadcasts這個(gè)集合的作用就是存儲(chǔ)和發(fā)送廣播的Action匹配的ReceiverRecord集合,在執(zhí)行處理廣播的時(shí)候,會(huì)將遍歷這個(gè)集合里面的廣播接收器,說(shuō)白了它是一個(gè)存儲(chǔ)了廣播接收器的存儲(chǔ)器。

它是一個(gè)廣播,肯定要注冊(cè),看一下registerReceiver這個(gè)方法

    public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
        synchronized (mReceivers) {
            ReceiverRecord entry = new ReceiverRecord(filter, receiver);
            ArrayList<IntentFilter> filters = mReceivers.get(receiver);
            if (filters == null) {
                filters = new ArrayList<IntentFilter>(1);
                mReceivers.put(receiver, filters);
            }
           //為廣播添加器添加指定的過(guò)濾規(guī)則
            filters.add(filter);
          //。。。。。。。。。
            for (int i=0; i<filter.countActions(); i++) {
                String action = filter.getAction(i);
                ArrayList<ReceiverRecord> entries = mActions.get(action);
                if (entries == null) {
                    entries = new ArrayList<ReceiverRecord>(1);
                    mActions.put(action, entries);
                }
               //把IntentFilter里面的所有Action分別建立對(duì)ArrayList<ReceiverRecord>的映射,也就是為相應(yīng)的Action添加廣播接收器,表示這個(gè)廣播接收器可以接收此Action的廣播
                entries.add(entry);
              //。。。。。。。
            }
        }
    }

看它所對(duì)應(yīng)的unregisterReceiver

    public void unregisterReceiver(BroadcastReceiver receiver) {
        synchronized (mReceivers) {
            ArrayList<IntentFilter> filters = mReceivers.remove(receiver);
            if (filters == null) {
                return;
            }
            for (int i=0; i<filters.size(); i++) {
                IntentFilter filter = filters.get(i);
                for (int j=0; j<filter.countActions(); j++) {
                    String action = filter.getAction(j);
                    ArrayList<ReceiverRecord> receivers = mActions.get(action);
                    if (receivers != null) {
                        for (int k=0; k<receivers.size(); k++) {
                            if (receivers.get(k).receiver == receiver) {
                                 //移除mReceivers表中廣播接收器
                                receivers.remove(k);
                                k--;
                            }
                        }
                        if (receivers.size() <= 0) {
                            //移除mActions表中的廣播接收器
                            mActions.remove(action);
                        }
                    }
                }
            }
        }
    }

它做了兩件事

1、移除mReceivers表中廣播接收器
2、移除mActions表中的廣播接收器

再看一下最重要的sendBroadcast

 public boolean sendBroadcast(Intent intent) {
        synchronized (mReceivers) {
            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();

            final boolean debug = DEBUG ||
                    ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
            if (debug) Log.v(
                    TAG, "Resolving type " + type + " scheme " + scheme
                    + " of intent " + intent);
            //通過(guò)得到我們Intent的Action來(lái)獲得該Action對(duì)應(yīng)的所有的廣播接收器的集合
            ArrayList<ReceiverRecord> entries = mActions.get(intent.getAction());
            if (entries != null) {
                if (debug) Log.v(TAG, "Action list: " + entries);

                ArrayList<ReceiverRecord> receivers = null;
                //然后遍歷該集合,進(jìn)行匹配
                for (int i=0; i<entries.size(); i++) {
                    ReceiverRecord receiver = entries.get(i);
                    if (debug) Log.v(TAG, "Matching against filter " + receiver.filter);

                    if (receiver.broadcasting) {
                        if (debug) {
                            Log.v(TAG, "  Filter's target already added");
                        }
                        continue;
                    }
                    //當(dāng)action,type,scheme,data,categories都完全相同時(shí),這時(shí)匹配成功
                    int match = receiver.filter.match(action, type, scheme, data,
                            categories, "LocalBroadcastManager");
                    if (match >= 0) {
                        //匹配成功
                        if (debug) Log.v(TAG, "  Filter matched!  match=0x" +
                                Integer.toHexString(match));
                        if (receivers == null) {
                            receivers = new ArrayList<ReceiverRecord>();
                        }
                        //然后把匹配成功的ReceiverRecord對(duì)象添加到一個(gè)集合中去
                        receivers.add(receiver);
                        receiver.broadcasting = true;
                    } else {
                        if (debug) {
                            String reason;
                            switch (match) {
                                case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;
                                case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;
                                case IntentFilter.NO_MATCH_DATA: reason = "data"; break;
                                case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;
                                default: reason = "unknown reason"; break;
                            }
                            Log.v(TAG, "  Filter did not match: " + reason);
                        }
                    }
                }

                if (receivers != null) {
                    for (int i=0; i<receivers.size(); i++) {
                        receivers.get(i).broadcasting = false;
                    }
                    //最后再把存儲(chǔ)匹配成功的ReceiverRecord對(duì)象集合添加到mPendingBroadcasts中去,而最終我們的廣播接收是通過(guò)遍歷mPendingBroadcasts這個(gè)集合來(lái)一一對(duì)這個(gè)集合里面的廣播接收器進(jìn)行廣播的接收
                    mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));

                    if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {
//這個(gè)非常重要,因?yàn)橐婚_(kāi)始我們就知道了在構(gòu)造函數(shù)中會(huì)創(chuàng)建一個(gè)handler,而這個(gè)方法的名為sendBroadcast()其實(shí)不是真正的發(fā)送一個(gè)廣播,而是通過(guò)handler來(lái)發(fā)送一個(gè)Message,然后在handlerMessage()回調(diào)方法中進(jìn)行消息的處理,所以這也證實(shí)了這是一個(gè)本地廣播,其它應(yīng)用根本無(wú)法獲取到,因?yàn)長(zhǎng)ocalBroadcastManager內(nèi)部是通過(guò)Handler實(shí)現(xiàn)廣播的發(fā)送的  
                    mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);
                    }
                    return true;
                }
            }
        }
        return false;
    }

這個(gè)sendBroadcast()方法看起來(lái)比較長(zhǎng),其實(shí)一半的代碼都是在做匹配,這段代碼也做了三件事:

1、把我們發(fā)送的Intent的規(guī)則和mActions中對(duì)應(yīng)action的ArrayList<ReceiverRecord>集合里面的廣播接收器的規(guī)則進(jìn)行匹配,匹配成功則加入一個(gè)匹配成功的集合中
2、把匹配成功的集合加入到mPendingBroadcasts集合中
3、最重要的一點(diǎn),它其實(shí)是通過(guò)handler發(fā)送一個(gè)Message來(lái)實(shí)現(xiàn)的

總結(jié) :LocalBroadcastManager高效的原因主要是因?yàn)樗鼉?nèi)部是通過(guò)Handler實(shí)現(xiàn)的,它的sendBroadcast()方法含義并非和我們平時(shí)所用的一樣,它的sendBroadcast()方法其實(shí)是通過(guò)handler發(fā)送一個(gè)Message實(shí)現(xiàn)的(當(dāng)然這個(gè)方法還有規(guī)則匹配等作用)
既然是它內(nèi)部是通過(guò)Handler來(lái)實(shí)現(xiàn)廣播的發(fā)送的,那么相比與系統(tǒng)廣播通過(guò)Binder實(shí)現(xiàn)那肯定是更高效了,同時(shí)使用Handler來(lái)實(shí)現(xiàn),別的應(yīng)用無(wú)法向我們的應(yīng)用發(fā)送該廣播,而我們應(yīng)用內(nèi)發(fā)送的廣播也不會(huì)離開(kāi)我們的應(yīng)用
LocalBroadcastManager內(nèi)部協(xié)作主要是靠這兩個(gè)Map集合:mReceivers和mActions,當(dāng)然還有一個(gè)List集合mPendingBroadcasts,這個(gè)主要就是存儲(chǔ)待接收的廣播對(duì)象
假如我們需要讓一個(gè)廣播接收器能接收多個(gè)不同Action的廣播,我們可以在注冊(cè)時(shí)候通過(guò)IntentFilter為該廣播添加多條Action規(guī)則,這樣只要符合其中一條該廣播接收器就可以接收到了,如下:

 //注冊(cè)
        IntentFilter filter = new IntentFilter();
        filter.addAction("com.sunzxy.demo.BROADCAST_ACTION_1");
        filter.addAction("com.sunzxy.demo.BROADCAST_ACTION_2");
        filter.addAction("com.sunzxy.demo.BROADCAST_ACTION_3");
        LocalBroadcastManager.getInstance(this).registerReceiver(new MyMyBroadcastReceiver(),filter);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容