定义:观察者模式就是监听一个对象的变化,当一个对象发生变化时,所有监听其变化的对象都会收到通知,Android中非常多的东西都是观察者模式的实现。
1.InCallStateListener
incallui,是一个mvp的经典实现,所有的presenter都会监听这个listener
1.1定义
/**
* Interface implemented by classes that need to know about the InCall State.
*/
public interface InCallStateListener {
// TODO: Enhance state to contain the call objects instead of passing CallList
public void onStateChange(InCallState oldState, InCallState newState, CallList callList);
}
一个接口,一个回调方法:onStateChange,可以说所有的数据变化都会通过onStateChange通知所有的presenter,之后会更新所有的ui。
1.2流程
以CallButtonPresenter为例,首先是注册:
@Override
public void onUiReady(CallButtonUi ui) {
super.onUiReady(ui);
mEnhanceEnable = ui.getContext().getResources().getBoolean(
R.bool.config_enable_enhance_video_call_ui);
AudioModeProvider.getInstance().addListener(this);
// register for call state changes last
final InCallPresenter inCallPresenter = InCallPresenter.getInstance();
inCallPresenter.addListener(this);
...
// Update the buttons state immediately for the current call
onStateChange(InCallState.NO_CALLS, inCallPresenter.getInCallState(),
CallList.getInstance());
}
public void addListener(InCallStateListener listener) {
Preconditions.checkNotNull(listener);
mListeners.add(listener);
}
在onUiReady时注册这些listener,onUiReady的回调也可以说是一个观察者模式
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mPresenter.onUiReady(getUi());
}
在fragment的onActivityCreated时,告知presenter。
@Override
public void onCallListChange(CallList callList) {
if (mInCallActivity != null && mInCallActivity.getCallCardFragment() != null &&
mInCallActivity.getCallCardFragment().isAnimating()) {
mAwaitingCallListUpdate = true;
return;
}
if (callList == null) {
return;
}
mAwaitingCallListUpdate = false;
InCallState newState = getPotentialStateFromCallList(callList);
InCallState oldState = mInCallState;
Log.d(this, "onCallListChange oldState= " + oldState + " newState=" + newState);
newState = startOrFinishUi(newState);
Log.d(this, "onCallListChange newState changed to " + newState);
// Set the new state before announcing it to the world
Log.i(this, "Phone switching state: " + oldState + " -> " + newState);
mInCallState = newState;
// notify listeners of new state
for (InCallStateListener listener : mListeners) {
Log.d(this, "Notify " + listener + " of state " + mInCallState.toString());
listener.onStateChange(oldState, mInCallState, callList);
}
if (isActivityStarted()) {
final boolean hasCall = callList.getActiveOrBackgroundCall() != null ||
callList.getOutgoingCall() != null;
mInCallActivity.dismissKeyguard(hasCall);
}
if (CallList.getInstance().isDsdaEnabled() && (mInCallActivity != null)) {
mInCallActivity.updateDsdaTab();
}
}
onStateChange的回调时机是onCallListChange,这里又是一个观察者模式,InCallPresenter监听了CallList,onCallListChange的回调时机
/**
* Sends a generic notification to all listeners that something has changed.
* It is up to the listeners to call back to determine what changed.
*/
private void notifyGenericListeners() {
for (Listener listener : mListeners) {
listener.onCallListChange(this);
}
}
/**
* Called when a single call has changed.
*/
public void onUpdate(Call call) {
Trace.beginSection("onUpdate");
PhoneAccountHandle ph = call.getAccountHandle();
Log.d(this, "onUpdate - " + call + " ph:" + ph);
try {
if (call.mIsActiveSub && ph != null) {
int sub = Integer.parseInt(ph.getId());
Log.d(this, "onUpdate - sub:" + sub + " mSubId:" + mSubId);
if(sub != mSubId) {
setActiveSubId(sub);
}
}
} catch (NumberFormatException e) {
Log.w(this,"Sub Id is not a number " + e);
}
onUpdateCall(call);
notifyGenericListeners();
Trace.endSection();
}
// onUpdate时notifyGenericListeners
private void update() {
Trace.beginSection("Update");
int oldState = getState();
// We want to potentially register a video call callback here.
updateFromTelecomCall(true /* registerCallback */);
if (oldState != getState() && getState() == Call.State.DISCONNECTED) {
CallList.getInstance().onDisconnect(this);
} else {
CallList.getInstance().onUpdate(this);
}
Trace.endSection();
}
// 在incallui/Call的update方法调用CallList.getInstance().onUpdate(this);
private final android.telecom.Call.Callback mTelecomCallCallback =
new android.telecom.Call.Callback() {
@Override
public void onStateChanged(android.telecom.Call call, int newState) {
Log.d(this, "TelecomCallCallback onStateChanged call=" + call + " newState="
+ newState);
update();
}
@Override
public void onParentChanged(android.telecom.Call call,
android.telecom.Call newParent) {
Log.d(this, "TelecomCallCallback onParentChanged call=" + call + " newParent="
+ newParent);
update();
}
@Override
public void onChildrenChanged(android.telecom.Call call,
List<android.telecom.Call> children) {
update();
}
@Override
public void onDetailsChanged(android.telecom.Call call,
android.telecom.Call.Details details) {
Log.d(this, "TelecomCallCallback onStateChanged call=" + call + " details="
+ details);
update();
}
@Override
public void onCannedTextResponsesLoaded(android.telecom.Call call,
List<String> cannedTextResponses) {
Log.d(this, "TelecomCallCallback onStateChanged call=" + call
+ " cannedTextResponses=" + cannedTextResponses);
update();
}
@Override
public void onPostDialWait(android.telecom.Call call,
String remainingPostDialSequence) {
Log.d(this, "TelecomCallCallback onStateChanged call=" + call
+ " remainingPostDialSequence=" + remainingPostDialSequence);
update();
}
@Override
public void onVideoCallChanged(android.telecom.Call call,
VideoCall videoCall) {
Log.d(this, "TelecomCallCallback onStateChanged call=" + call + " videoCall="
+ videoCall);
update();
}
@Override
public void onCallDestroyed(android.telecom.Call call) {
Log.d(this, "TelecomCallCallback onStateChanged call=" + call);
call.unregisterCallback(this);
}
@Override
public void onConferenceableCallsChanged(android.telecom.Call call,
List<android.telecom.Call> conferenceableCalls) {
update();
}
@Override
public void onConnectionEvent(android.telecom.Call call, String event, Bundle extras) {
Log.d(this, "TelecomCallCallback onConnectionEvent call=" + call);
update();
}
};
还是一个观察者模式,incallui/Call监听的是telecom/Call,telecom/Call的变化传递到incallui/Call,incallui/Call的变化传递到CallList的变化,最后导致InCallState的变化。
可以看到整个incallui几乎都是一个观察者模式的实现。
1.3总结
在设计UI的时候观察者模式一定是被优先考虑的,因为Ui就是显示数据的,当数据发生变化时,UI就要实时地发生变换,自然而然就会使用到观察者模式,它的好处就是当数据没有变化时,UI不需要更新,当数据发生变化时,UI又能第一时间收到变化的通知,并更新UI,所以对需要实时更新的UI来讲,观察者模式是一个非常好的模式。
2.广播
Android中广播用的也是非常多,但其实广播其实就是一个观察者模式的实现。通过广播可以突破进程限制,跨进程地通知所有的观察者,所以这个广播是注册在哪里?如果跨进程进行运作。这里简单地看一下广播的注册和接收流程
2.1注册广播
注册广播一般都会食用mContext.registerReceiver(..),最终会调用到ContextImpl的registerReceiverInternal方法
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context) {
IIntentReceiver rd = null;//这是一个bindler对象,通过它与AMS交互
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
try {
final Intent intent = ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
// 这里可以看到调用了ActivityManagerNative的registerReceiver
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess();
}
return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
可以看到最终调用了ActivityManagerNative.getDefault().registerReceiver(),所以其实可以猜测广播会注册在AMS中,其中非常重要的一个东西就是IIntentReceiver rd,AMS将通过它来将其他进程发送的广播通知到这个receiver所在的进程,具体在接受广播时在来看ReceiverDispatcher。
AMS中的registerReceiver方法:
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
// 省略一些逻辑
synchronized (this) {
if (callerApp != null && (callerApp.thread == null
|| callerApp.thread.asBinder() != caller.asBinder())) {
// Original caller already died
return null;
}
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
if (rl.app != null) {
rl.app.receivers.add(rl);
} else {
try {
receiver.asBinder().linkToDeath(rl, 0);
} catch (RemoteException e) {
return sticky;
}
rl.linkedToDeath = true;
}
mRegisteredReceivers.put(receiver.asBinder(), rl);
} else if (rl.uid != callingUid) {
throw new IllegalArgumentException(
"Receiver requested to register for uid " + callingUid
+ " was previously registered for uid " + rl.uid);
} else if (rl.pid != callingPid) {
throw new IllegalArgumentException(
"Receiver requested to register for pid " + callingPid
+ " was previously registered for pid " + rl.pid);
} else if (rl.userId != userId) {
throw new IllegalArgumentException(
"Receiver requested to register for user " + userId
+ " was previously registered for user " + rl.userId);
}
// 省略sticky的逻辑
}
}
可以将这个receiver保存到了mRegisteredReceivers中。这样广播的注册就结束了
2.2发送广播
同样发送广播也会调用到ContextImpl的sendBroadcast方法
@Override
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess(this);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
又调用到AMS中去broadcastIntent->broadcastIntentLocked->scheduleBroadcastsLocked
public void scheduleBroadcastsLocked() {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
+ mQueueName + "]: current="
+ mBroadcastsScheduled);
if (mBroadcastsScheduled) {
return;
}
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
final class BroadcastHandler extends Handler {
public BroadcastHandler(Looper looper) {
super(looper, null, true);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
if (DEBUG_BROADCAST) Slog.v(
TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
processNextBroadcast(true);
} break;
case BROADCAST_TIMEOUT_MSG: {
synchronized (mService) {
broadcastTimeoutLocked(true);
}
} break;
case SCHEDULE_TEMP_WHITELIST_MSG: {
DeviceIdleController.LocalService dic = mService.mLocalDeviceIdleController;
if (dic != null) {
dic.addPowerSaveTempWhitelistAppDirect(UserHandle.getAppId(msg.arg1),
msg.arg2, true, (String)msg.obj);
}
} break;
}
}
}
最后会调用到scheduleRegisteredReceiver
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky, int sendingUser, int processState) throws RemoteException {
updateProcessState(processState, false);
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
所以最后还是调用到IIntentReceiver的performReceive方法
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
if (intent == null) {
Log.wtf(TAG, "Null intent received");
} else {
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
+ " seq=" + seq + " to " + mReceiver);
}
}
if (intent == null || !mActivityThread.post(args)) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManagerNative.getDefault();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
args.sendFinished(mgr);
}
}
}
z这个args就是一个runable
final class Args extends BroadcastReceiver.PendingResult implements Runnable {
private Intent mCurIntent;
private final boolean mOrdered;
private boolean mDispatched;
public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
boolean ordered, boolean sticky, int sendingUser) {
super(resultCode, resultData, resultExtras,
mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
mCurIntent = intent;
mOrdered = ordered;
}
public void run() {
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;
if (ActivityThread.DEBUG_BROADCAST) {
int seq = mCurIntent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
+ " seq=" + seq + " to " + mReceiver);
Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered
+ " mOrderedHint=" + ordered);
}
final IActivityManager mgr = ActivityManagerNative.getDefault();
final Intent intent = mCurIntent;
if (intent == null) {
Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched);
}
mCurIntent = null;
mDispatched = true;
if (receiver == null || intent == null || mForgotten) {
if (mRegistered && ordered) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing null broadcast to " + mReceiver);
sendFinished(mgr);
}
return;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);//调用onReceive
} catch (Exception e) {
if (mRegistered && ordered) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing failed broadcast to " + mReceiver);
sendFinished(mgr);
}
if (mInstrumentation == null ||
!mInstrumentation.onException(mReceiver, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Error receiving broadcast " + intent
+ " in " + mReceiver, e);
}
}
if (receiver.getPendingResult() != null) {
finish();
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
可以看到在这里调用了onReceive方法,广播接收完成。中间跳过了非常多的步骤,因为这里的逻辑还是非常的复杂,但是最终原理就是这样,广播注册在AMS中,通过AMS传递广播