Compont源码分析

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

实现Componentpublic 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,之后通过调用ComponentonCall方法,做真正的请求.
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子类中手动调用ComponentClientsendResult方法,将结果返回.

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模式,即先返回一个对象,这个对象会等待真正的结果返回.

你可能感兴趣的:(Compont源码分析)