android 本地广播原理,Android本地广播详解

本地广播用途

math?formula=~~~~本地广播用于同一个app内通信(是否可以多进程通信?),且其他app无法接收到本地广播的消息,可以大大提高安全性,且只能动态注册。

本地广播的使用和原理分析

本地广播使用到的几个类

math?formula=~~~~1、public final class LocalBroadcastManager这个类是无法继承的,直接使用即可,后续我们深入分析这个类。

math?formula=~~~~2、public abstract class BroadcastReceiver这个类是抽象类,在使用过程中一般需要继承,实现onReceive函数。后续我们会分析为什么需要继承这个类且为什么要实现onReceive函数。

math?formula=~~~~3、public class IntentFilter implements Parcelable这个类是用于添加本地广播Inten过滤动作的,且我们后续会深入分析这个类。

本地广播实现源代码

math?formula=~~~~1、新建一个BroadcastTest工程,创建一个空的活动即可,在MainActivity中增加若干私有成员,新建一个LocalReceiver类继承BroadcastReceiver并重写onReceive函数,以下是一些代码片段,后续我也会先贴出片段代码方便分析,最后再贴出完整代码。

public class MainActivity extends AppCompatActivity {

private IntentFilter intentFilter;

private static final String TAG="MainActivity";

private LocalReceiver localReceiver;

private LocalBroadcastManager localBroadcastManager;

private static final String localBroadcastAction = "com.example.broadcasttest.LOCAL_BROADCAST";

private class LocalReceiver extends BroadcastReceiver{

@Override

public void onReceive(Context context, Intent intent) {

Toast.makeText(context, "received a localbroadcast", Toast.LENGTH_SHORT).show();

}

}

math?formula=~~~我们跳进BroadcastReceiver找到onReceive函数,源代码如下:

*

* @param context The Context in which the receiver is running.

* @param intent The Intent being received.

*/

public abstract void onReceive(Context context, Intent intent);

math?formula=~~~~从这里我们可以看出onReceive函数是抽象函数,所以我们需要重新实现这个函数。刚开始学习Android的时候通常我们会看到书上说我们要实现xxx函数,但是通常不会告诉我们为什么要重新实现这个函数,而且函数的参数是哪些也都不知道。这个时候我们可以点开源码,阅读源码知根知底。关于如何调用onReceive后面会详细分析。

math?formula=~~~~2、创建一个按钮控件,方便后面测试,按下按钮使用本地广播发送一条消息,并用Toast显示。

math?formula=~~~~3、在MainActivity的onCreate函数中进行初始化变量,注册按钮监听器。

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

localBroadcastManager = LocalBroadcastManager.getInstance(this);

Button button = (Button)findViewById(R.id.button);

button.setOnClickListener(new View.OnClickListener(){

@Override

public void onClick(View view){

Log.d(TAG, "button clicked");

Intent intent = new Intent(localBroadcastAction);

localBroadcastManager.sendBroadcast(intent);

//localBroadcastManager.sendBroadcastSync(intent);

}

});

IntentFilter intentFilter = new IntentFilter();

intentFilter.addAction(localBroadcastAction);

localReceiver = new LocalReceiver();

localBroadcastManager.registerReceiver(localReceiver, intentFilter);

math?formula=~~~~进入LocalBroadcastManager源码我们发现该类的构造函数是私有的,也就是我们无法通过new创建LocalBroadcastManager的实例,而且还发现它有一个静态私有的LocalBroadcastManager成员变量,那么意思很明显了,只能通过一个公有的方法获取LocalBroadcastManager单例对象实例。

private static final Object mLock = new Object();

private static LocalBroadcastManager mInstance;

@NonNull

public static LocalBroadcastManager getInstance(@NonNull Context context) {

synchronized (mLock) {

if (mInstance == null) {

mInstance = new LocalBroadcastManager(context.getApplicationContext());

}

return mInstance;

}

}

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

}

}

};

}

math?formula=~~~通过代码我们知道,基于懒汉式单例模式通过公有方法getInstance创建对象实例,所以我们只能通过调用getInstance函数获取LocalBroadcastManager对象实例。从构造函数我们也能大概猜出,初始化的过程中创建了一个线程处理发送的广播消息。由于本地广播可以发送多条消息,因此要想接收到指定的本地广播消息,则需要一个广播消息ID。IntentFilter则是通过存储本地广播消息ID,并和广播接收器BroadcastReceiver绑定在一起实现接收指定的广播数据。

* @param action Name of the action to match, such as Intent.ACTION_VIEW.

*/

public final void addAction(String action) {

if (!mActions.contains(action)) {

mActions.add(action.intern());

}

}

@UnsupportedAppUsage

private final ArrayList mActions;

* @see #unregisterReceiver

*/

public void registerReceiver(@NonNull BroadcastReceiver receiver,

@NonNull IntentFilter filter) {

synchronized (mReceivers) {

ReceiverRecord entry = new ReceiverRecord(filter, receiver);

ArrayList filters = mReceivers.get(receiver);

if (filters == null) {

filters = new ArrayList<>(1);

mReceivers.put(receiver, filters);

}

filters.add(entry);

for (int i=0; i

String action = filter.getAction(i);

ArrayList entries = mActions.get(action);

if (entries == null) {

entries = new ArrayList(1);

mActions.put(action, entries);

}

entries.add(entry);

}

}

}

private static final class ReceiverRecord {

final IntentFilter filter;

final BroadcastReceiver receiver;

boolean broadcasting;

boolean dead;

ReceiverRecord(IntentFilter _filter, BroadcastReceiver _receiver) {

filter = _filter;

receiver = _receiver;

}

IntentFilter将action存储在ArrayList中,LocalBroadcastManager的registerReceiver函数将传入的receiver和filter通过ReceiverRecord绑定在一起,实现了接收特定本地广播消息的功能。

math?formula=~~~4、调用sendBroadcast将本地广播消息发送出去(实际上只是把数据放在了一个消息队列里面,线程异步将消息发送出去),我们直接点开sendBroadcast源码,以下是代码片段。

if (receivers != null) {

for (int i=0; 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;

}

math?formula=~~~~从源码我们知道,存储Intent并发送一条广播消息到消息队列里面,并且将receiver和BroadcastRecord联系在一起,且将BroadcastRecord存储在mPendingBroadcasts里面。我们进入LocalBroadcastManager的构造函数调用的executePendingBroadcasts函数源码。

void executePendingBroadcasts() {

while (true) {

final BroadcastRecord[] brs;

synchronized (mReceivers) {

final int N = mPendingBroadcasts.size();

if (N <= 0) {

return;

}

brs = new BroadcastRecord[N];

mPendingBroadcasts.toArray(brs);

mPendingBroadcasts.clear();

}

for (int i=0; i

final BroadcastRecord br = brs[i];

final int nbr = br.receivers.size();

for (int j=0; j

final ReceiverRecord rec = br.receivers.get(j);

if (!rec.dead) {

rec.receiver.onReceive(mAppContext, br.intent);

}

}

}

}

math?formula=~~~~从mPendingBroadcasts中取出BroadcastRecord对象实例,获取调用receiver,调用onReceive函数。这就是我们为什么可以在onReceive函数中接收到本地广播消息了。

总结

math?formula=~~~~本地广播的基本原理和使用我们已经讲得差不多了,其实还有很多没有讲到。但是没办法,要是把全部实现源代码追踪下去,无穷无尽。所以点到为止,继续学习后续的知识,先应付工作先。

math?formula=~~~~我们在学习Android的时候不仅仅学习表面如何使用,也要适当的追踪源码,学习底层实现原理。Android实在是知识太丰富了,有很多可以学习的地方,如果不是时间有限,真想把所有知识点追踪下去。

完整代码

package com.example.broadcasttest;

import androidx.appcompat.app.AppCompatActivity;

import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import android.app.admin.NetworkEvent;

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.Intent;

import android.content.IntentFilter;

import android.net.ConnectivityManager;

import android.net.Network;

import android.net.NetworkCapabilities;

import android.net.NetworkInfo;

import android.os.Bundle;

import android.util.Log;

import android.view.View;

import android.widget.Button;

import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

private IntentFilter intentFilter;

private static final String TAG="MainActivity";

private LocalReceiver localReceiver;

private LocalBroadcastManager localBroadcastManager;

private static final String localBroadcastAction = "com.example.broadcasttest.LOCAL_BROADCAST";

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

localBroadcastManager = LocalBroadcastManager.getInstance(this);

Button button = (Button)findViewById(R.id.button);

button.setOnClickListener(new View.OnClickListener(){

@Override

public void onClick(View view){

Log.d(TAG, "button clicked");

Intent intent = new Intent(localBroadcastAction);

localBroadcastManager.sendBroadcast(intent);

//localBroadcastManager.sendBroadcastSync(intent);

}

});

IntentFilter intentFilter = new IntentFilter();

intentFilter.addAction(localBroadcastAction);

localReceiver = new LocalReceiver();

localBroadcastManager.registerReceiver(localReceiver, intentFilter);

}

private class LocalReceiver extends BroadcastReceiver{

@Override

public void onReceive(Context context, Intent intent) {

Toast.makeText(context, "received a localbroadcast", Toast.LENGTH_SHORT).show();

}

}

public void onDestroy(){

super.onDestroy();

localBroadcastManager.unregisterReceiver(localReceiver);

}

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值