Compont源码分析
使用说明
1. 实现Component
接口创建子类
@SharedConst
public class MsgComponent implements Component {
private static final String FUNCTION_1 = "showToast";
private static final String FUNCTION_2 = "showToastAsync";
@Override
public boolean onCall(RealCaller caller) {
String actionName = caller.actionName();
if (FUNCTION_1.equals(actionName)) {
Context context = caller.getParamValue("context");
if (context != null) {
Toast.makeText(context, "有内鬼,终止交易!", Toast.LENGTH_SHORT).show();
}
return false;
} else if (FUNCTION_2.equals(actionName)) {
ComponentResult result = new ComponentResult();
result.addData("result", "有内鬼,终止交易!");
ComponentClient.sendResult(caller.getCallId(), result);
return true;
}
return false;
}
}
实现Component
的public boolean onCall(RealCaller caller)
方法.
返回值表示是否异步,true
表示异步.
2. 定义方法名,并在onCall
中区分对应的实现
其中,异步方法的结果要通过public static void sendResult(String callId, ComponentResult result)
返回.
原理
该方法最终会根据传入的callId
找到对应的RealCaller
,并调用setResultForWaiting(ComponentResult result)
方法,将结果返回.
static void sendResult(String callId, ComponentResult result) {
RealCaller caller = ComponentMonitor.getCallerById(callId);
if (caller != null) {
if (caller.markFinished()) {
if (result == null) {
result = ComponentResult.defaultNullResult();
}
caller.setResultForWaiting(result);
}
}
}
3. 同步调用
ComponentResult rst = ComponentClient.obtainBuilder("MsgComponent")
.setActionName("showToast")
.addParam("param_from", "[同步]")
.build()
.call();
Toast.makeText(getContext(), "" + rst.getData().get("result"), Toast.LENGTH_SHORT).show();
4. 异步调用
ComponentClient.obtainBuilder("MsgComponent")
.setActionName("showToastAsync")
.addParam("param_from", "[异步]")
.build()
.callAsync(new ComponentCallback() {
@Override
public void onResult(Caller caller, ComponentResult result) {
AppExecutors.getInstance().mainThread().execute(new Runnable() {
@Override
public void run() {
Toast.makeText(getContext(), "" + result.getData().get("result"), Toast.LENGTH_SHORT).show();
}
});
}
});
源码分析
3个Interceptor
类
-
VerifyInterceptor
:对Component
做校验; -
WaitForResultInterceptor
:对结果做等待;这里会对结果加锁. -
CallServiceInterceptor
:真实的调用;
CallServiceInterceptor
中会将Component
请求封装在CallServiceRunnable
,之后通过调用Component
的onCall
方法,做真正的请求.
onCall
里就是我们在Component
子类中的具体实现.
1个Future
模式
onCall
的返回值,表明是否为异步调用.如果为true
,表示异步获取结果;否则,同步.
如果在同步调用时,没有直接返回结果,会自动返回默认结果.
static class CallServiceRunnable implements Runnable {
@Override
public void run() {
boolean callbackDelay = component.onCall(mCaller);
//如果是同步回调接口,并且没有主动发送结果。
if (!callbackDelay && !mCaller.isFinished()) {
setResult(ComponentResult.defaultNullResult());
}
}
}
异步必须在我们自定义的Component
子类中手动调用ComponentClient
的sendResult
方法,将结果返回.
ComponentResult result = new ComponentResult();
result.addData("result", "有内鬼,终止交易!");
ComponentClient.sendResult(caller.getCallId(), result);
这里sendResult
方法中,会将在WaitForResultInterceptor
中加的锁解开,从而允许结果返回.
static void sendResult(String callId, ComponentResult result) {
RealCaller caller = ComponentMonitor.getCallerById(callId);
if (caller != null) {
if (caller.markFinished()) {
if (result == null) {
result = ComponentResult.defaultNullResult();
}
caller.setResultForWaiting(result);
}
}
}
caller.markFinished()
中会将锁解开,并通知等待线程,从而继续将结果返回.
这个过程非常像J.U.C
中的Future
模式,即先返回一个对象,这个对象会等待真正的结果返回.