返回介绍

3. 源码解析

发布于 2024-12-23 21:44:25 字数 7801 浏览 0 评论 0 收藏 0

3.1 LocalBroadcastManager 原理概要

LocalBroadcastManager 使用单例模式对象,初始化时会在内部初始化一个 Handler 对象用来接受广播。注册广播时,会将自定义的 BroadcastReceiver 对象和 IntentFilter 对象保存到 HashMap 中。发送广播时,则根据 IntentFilter 的 Action 值从已保存的 HashMap 找到对应接受者,并发送 Handler 消息去执行 receiver 的 onReceive 方法。

LocalBroadcastManager 核心代码为以下四个函数。

  • registerReceiver(BroadcastReceiver receiver, IntentFilter filter) //注册广播函数
  • unregisterReceiver(BroadcastReceiver receiver) //取消注册函数
  • sendBroadcast(Intent intent) //发送广播
  • executePendingBroadcasts() //处理接受到的广播

3.2 LocalBroadcastManager 基本数据结构

LocalBroadcastManager 需要保存三样东西,一个是 mReceivers , 用来保存已注册的自定义的 receiver 和 intentFilter。一个是 mActions 键值对,保存 action 和 ReceiverRecord 列表的键值对。一个是 mPendingBroadcasts , 用来保存待通知的 receiver 对象。

 //注册广播 Record 类
 private static class ReceiverRecord {
    final IntentFilter filter;
    final BroadcastReceiver receiver;
    boolean broadcasting;
    
    ReceiverRecord(IntentFilter _filter, BroadcastReceiver _receiver) {
      filter = _filter;
      receiver = _receiver;
    }
    ...
 }

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

//待广播的 Record 类
private static class BroadcastRecord {
  final Intent intent;
  final ArrayList<ReceiverRecord> receivers;

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

3.3 注册广播

将需要注册的 receiver 对象和该 receiver 需要监听的 filter 保存到 mReceiversmPendingBroadcasts 中。

/**
 * Register a receive for any local broadcasts that match the given IntentFilter.
 *
 * @param receiver The BroadcastReceiver to handle the broadcast.
 * @param filter Selects the Intent broadcasts to be received.
 *
 * @see #unregisterReceiver
 */
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);  //保存 receiver 和 filter 到 List
    }
    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);   //保存到 action 和 ReceiverRecord 到 HashMap
      }
      entries.add(entry);
    }
  }
}

3.4 取消广播注册

根据 receiver 对象移除 mReceiversmPendingBroadcasts 中对应的对象。

/**
 * Unregister a previously registered BroadcastReceiver.  All
 * filters that have been registered for this BroadcastReceiver will be
 * removed.
 *
 * @param receiver The BroadcastReceiver to unregister.
 *
 * @see #registerReceiver
 */
public void unregisterReceiver(BroadcastReceiver receiver) {
  synchronized (mReceivers) {
    //从 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) {
              receivers.remove(k);
              k--;
            }
          }
          if (receivers.size() <= 0) {
            mActions.remove(action);  //从 mActions 中移除
          }
        }
      }
    }
  }
}

3.5 通过 Handler 发送广播

发送广播时,先根据 intent 中的 action 到 mActions 中找到对应的记录,然后再完整匹配 filter 里面的各个字段,若匹配成功,则将对应的 receiver 添加的 mPendingBroadcasts 列表中,等待 handler 对象的 handleMessage() 方法处理。

/**
 * Broadcast the given intent to all interested BroadcastReceivers.  This
 * call is asynchronous; it returns immediately, and you will continue
 * executing while the receivers are run.
 *
 * @param intent The Intent to broadcast; all receivers matching this
 *   Intent will receive the broadcast.
 *
 * @see #registerReceiver
 */
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();

		  ...

    //根据 intent 的 action 寻找 ReceverRecord
    ArrayList<ReceiverRecord> entries = mActions.get(intent.getAction());
    
    if (entries != null) {
 
      ArrayList<ReceiverRecord> receivers = null;
      for (int i=0; i<entries.size(); i++) {
      
        ReceiverRecord receiver = entries.get(i);
					//相同的 receiver,只添加一次 
        if (receiver.broadcasting) {
          continue;
        }

        int match = receiver.filter.match(action, type, scheme, data,
            categories, "LocalBroadcastManager");

        if (match >= 0) {
          if (receivers == null) {
            receivers = new ArrayList<ReceiverRecord>();
          }
          receivers.add(receiver);
          //标记为已添加,待广播状态 
          receiver.broadcasting = true;
        } else {
 						...
        }
      }

      if (receivers != null) {
      
      		//receivers 添加完成后,将 broadcasting 状态回归
        for (int i=0; i<receivers.size(); i++) {
          receivers.get(i).broadcasting = false;
        }
        
        //添加到待广播列表
        mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));
        
        //若无正在处理的消息,则 handler 发送广播消息
        if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {
          mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);
        }
        
        return true;
      }
    }
  }
  return false;

3.6 Handler 接受和消费广播

在 handler 对象的 handleMessage() 方法中遍历 mPendingBroadcasts 列表,依次循环调用其中的 onReceive() 方法,并将 intent 中的数据传入,从而消费广播信息。

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

private void executePendingBroadcasts() {
  while (true) {
    BroadcastRecord[] brs = null;
    synchronized (mReceivers) {
      final int N = mPendingBroadcasts.size();
      if (N <= 0) {
        return;
      }
      //拷贝数据到 brs 数组
      brs = new BroadcastRecord[N];
      mPendingBroadcasts.toArray(brs);
      mPendingBroadcasts.clear();
    }
    
    for (int i=0; i<brs.length; i++) {
      BroadcastRecord br = brs[i];
      for (int j=0; j<br.receivers.size(); j++) {
        //循环数组里的内容,调用其 onReceive 方法,消费广播内容
        br.receivers.get(j).receiver.onReceive(mAppContext, br.intent);
      }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文