Android本地广播和全局广播的区别及实现原理

版权声明:本文为博主原创文章,转载希望能注明出处,感谢。 https://blog.csdn.net/u010126792/article/details/82417190

迷茫时该如何选择?

1.本地广播和全局广播

1.1本地广播:

         广播事件的发送和接收都在本应用,不影响其他应用也不受其他应用影响,只能被动态注册,不能静态注册,主要用法都在LocalBroadcastManager类中。

1.2全局广播:

         可以接收其他应用发的广播,也可以发送广播让其他应用接收,全局广播既可以动态注册,也可以静态注册,接受其他应用和系统广播是全局广播的一个重要应用点。总体来说两者应用场景不同。

全局广播发送和接收限制设置:

(1)不让别的应用收到自己发送的广播

在Androidmanifest.xml中为BroadcastReceiver添加权限,如果是自定义权限记得先声明:

<permission android:name = "com.android.permission.quanxian"/>

发送广播是传入:

public void sendOrderedBroadcast(Intent intent, String receiverPermission)

sendBroadcast(intent, "com.android.permission.quanxian ");

只有具有permission权限的Receiver才能接收此广播要接收该广播,在Receiver应用的AndroidManifest.xml中要添加对应的相应的权限。 

(2)过滤掉自己不愿接收的广播。

android:exported  此broadcastReceiver能否接收其他App的发出的广播,这个属性默认值有点意思,其默认值是由receiver中有无intent-filter决定的,如果有intent-filter,默认值为true,否则为false。

android:permission设置之后,只有具有相应权限的广播发送方发送的广播才能被此broadcastReceiver所接收;

        上述设置也可以达到接收或者不接收的目的,但是全局广播其实原理是利用binder机制和AMS进行交互如果只是应用内使用,资源耗费或者说延时还是可以优化的。

2 本地广播使用

public class Demo3 extends AppCompatActivity {
    private MyBroadcastReceiver mBroadcastReceiver;
    private TextView mTv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTv = findViewById(R.id.clicke);
        initEvent();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.ldx.demo");
        LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, intentFilter);
    }

    private void initEvent() {
        mTv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setAction("com.ldx.demo");
                LocalBroadcastManager.getInstance(Demo3.this).sendBroadcast(intent);
            }
        });
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
    }

    class MyBroadcastReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {

        }
    }
}

3 本地广播的实现原理

单例LocalBroadcastManager

全部逻辑都在LocalBroadcastManager中,LocalBroadcastManager提供了单例获取的getInstance:

@NonNull
public static LocalBroadcastManager getInstance(@NonNull Context context) {
    synchronized (mLock) {
        if (mInstance == null) {
            mInstance = new LocalBroadcastManager(context.getApplicationContext());
        }
        return mInstance;
    }
}

同时初始化了一个Handler:

private LocalBroadcastManager(Context context) {
    mAppContext = context;

       //利用主线程looper构造handler
    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);
            }
        }
    };
}

所以猜测是利用Handler向Receiver发送信息。

两个静态final内部类:

static final class ReceiverRecord

static final class BroadcastRecord 

ReceiverRecord

ReceiverRecord:用来标识注册的单个广播,包括intentFilter和receiver,每次注册就会生成一个ReceiverRecord。

private static final class ReceiverRecord {

     //记录intentFilter,意图过滤
    final IntentFilter filter;

     //记录广播接收者
    final BroadcastReceiver receiver;
    boolean broadcasting;
    boolean dead;

    ReceiverRecord(IntentFilter _filter, BroadcastReceiver _receiver) {
        filter = _filter;
        receiver = _receiver;
    }
}

BroadcastRecord

BroadcastRecord记录一个意图对应的多个接收者,发送回复信息给Receiver时可以通过这个结构查找接收者。

private static final class BroadcastRecord {

//记录当前意图   
 final Intent intent;
//符合意图的ReceiverRecord

    final ArrayList<ReceiverRecord> receivers;

    BroadcastRecord(Intent _intent, ArrayList<ReceiverRecord> _receivers) {

        intent = _intent;

        receivers = _receivers;

    }

}

LocalBroadcastManager中变量

//当前所有注册广播

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

//有特定意图的广播
private final HashMap<String, ArrayList<ReceiverRecord>> mActions = new HashMap<>();
//待发送的广播
private final ArrayList<BroadcastRecord> mPendingBroadcasts = new ArrayList<>();

static final int MSG_EXEC_PENDING_BROADCASTS = 1;

private final Handler mHandler;

注册广播:

public void registerReceiver(@NonNull BroadcastReceiver receiver,

        @NonNull IntentFilter filter) {

    synchronized (mReceivers) {
       // 新的注册,生成ReceiverRecord

        ReceiverRecord entry = new ReceiverRecord(filter, receiver);

        ArrayList<ReceiverRecord> filters = mReceivers.get(receiver);
       //     最终添加到mReceivers中,一个广播接受者可能有多个意图过滤,场景类似对同一个BroadcastReceiver多次调用registerReceiver,每次意图过滤都不相同。

        if (filters == null) {

            filters = new ArrayList<>(1);

            mReceivers.put(receiver, filters);

        }

        filters.add(entry);
       //遍历意图过滤,获取action,每个action 对应多个ReceiverRecord,也就是一个Action对应多个接收者

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

            }

            entries.add(entry);

        }

    }

}

解除注册广播:

public void unregisterReceiver(@NonNull BroadcastReceiver receiver) {

    synchronized (mReceivers) {
       //从mReceivers中删除注册的广播,返回它的意图过滤列表

        final ArrayList<ReceiverRecord> filters = mReceivers.remove(receiver);

        if (filters == null) {

            return;

        }

       //遍历意图过滤列表
 for (int i=filters.size()-1; i>=0; i--) {
              //通过意图找到对应的ReceiverRecord

            final ReceiverRecord filter = filters.get(i);

            filter.dead = true;
              //找到所有对应的Action

            for (int j=0; j<filter.filter.countActions(); j++) {

                final String action = filter.filter.getAction(j);

               //从mActions中获取ReceiverRecord,因为一个Action对应多个ReceiverRecord,解注册之后需要删除对应的RR
 final ArrayList<ReceiverRecord> receivers = mActions.get(action);

                if (receivers != null) {

                    for (int k=receivers.size()-1; k>=0; k--) {

                        final ReceiverRecord rec = receivers.get(k);

                        if (rec.receiver == receiver) {

                            rec.dead = true;

                            receivers.remove(k);

                        }

                    }
                    //删除之后如果当前Action对应的RR没有了,就直接删除,应为不需要此Action对应RR了

                    if (receivers.size() <= 0) {

                        mActions.remove(action);

                    }

                }

            }

        }

    }

}

发送广播:

public boolean sendBroadcast(@NonNull Intent intent) {

    synchronized (mReceivers) {

       //首先获取Action及其他参数
 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);
//获取Action对应的ReceiverRecord

        ArrayList<ReceiverRecord> entries = mActions.get(intent.getAction());

        if (entries != null) {

            if (debug) Log.v(TAG, "Action list: " + entries);



            ArrayList<ReceiverRecord> receivers = null;

            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) {

                    continue;

                }



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

                    }
       //符合条件,修改状态为true,receivers为需要接受的列表

                    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;

                }
              //加入到发送列表中,等待发送

                mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));

                if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {

                    mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);

                }

                return true;

            }

        }

    }

    return false;

}

猜你喜欢

转载自blog.csdn.net/u010126792/article/details/82417190