在微信登陆成功之后把微信返回的code通过Autorize类的sendWXLoginAuther方法将这个code传给我们自己的后台
这里开始详细讲Autorize类。这个类至关重要
上文讲到Autorize类的sendWXLoginAuther方法,这个方法里里面将调用内部的两个方法,一个
private void startAuthorize(String authCode) {
prepareAuthorize();
mConnector.openConnection(authCode);
}
这两个方法,第一个是
private void prepareAuthorize() {
NetworkEngineUtils.prepareEngine(mHosts);
}
这个是准备NetworkEngine
最终prepareEngin的实现是
public static void prepareEngine(NetworkAddress[] hosts, long ssoPresent, String key) {
if (key == null) key = DEFAULT_KEY;
NetworkEngine.shareEngine().setDefultkey(ssoPresent, StringHelper.getUtf8Code(key));
String[] ips = new String[hosts.length];
int[] port = new int[hosts.length];
NetworkAddress.split(hosts, ips, port);
NetworkEngine.shareEngine().setHosts(NetworkEngine.CONN_TYPE_DIR, ips, port);
}
NetworkEngine.shareEngine().setDefultkey(ssoPresent, StringHelper.getUtf8Code(key));
这句代码得分几步看
- shareEngine(),这里初始化了一个JAVA层的NetWorkEngine,这个NetWorkEngine在初始化的时候调用native_create同时初始化c++层的NetWorkEngin—在engine_jni.cpp文件可以找到
setDefultkey,将参数设置进C++层的NetWorkEngine—–在engine_jni.cpp文件可以找到
NetworkEngine.shareEngine().setHosts(NetworkEngine.CONN_TYPE_DIR, ips, port);
这句代码则是设置host,也就是ip地址
public void setHosts(int type, String[] hosts, int[] ports)
{
try
{
native_set_hosts(type, hosts, ports);
}
catch (UnsatisfiedLinkError e)
{
}
}
可以看到在NetWorkEngine中直接就调用了native方法,这里就到了C++层,这个native_set_hosts在c++层最终调用的是C++的NetworkEngine的set_host_list方法
看实现
void set_host_list(int type, const std::vector<std::string> &hosts, const std::vector<int> &ports)
{
qt_base::CritScope cs(&crit_);
Channel *ch = getAndCreateChannel(type);
if (ch != NULL) {
ch->set_host_list(hosts, ports);
}
}
从实现中可以看出,C++层的NetWorkEngine在收到ip之后,第一步是创建了一个Channel,然后把ip传给了channel,
转看Channel的这个set方法
void set_host_list(const std::vector<std::string> &hosts, const std::vector<int> &ports)
{
hosts_.clear();
ports_.clear();
hosts_ = hosts;
ports_ = ports;
if (conn_ != NULL && !hosts.empty() && !ports.empty())
{
conn_->SetHostList(hosts_, ports_);
}
}
Channel又有一个关键的属性,那就是connector,也就是这conn_,在network\jni\network目录下,真正的连接都是在这里,包括超时时间等.而这个connector有一个SendRequest方法,这个SendRequest又是调用了protocolDriver的SendRequest方法,而protocolDriver持有一个IOLooper,这个是消息队列,所谓protocolDriver的sendRequest也就是把request放到了IOLooper这个消息队列中,IOLooper这个队列里面会自己开启一个线程去不断的执行网络请求,并且把返回向上回调回去,也就是我们在java层最终收到的listener(或则叫callBack也行)
发送正常请求流程
从Resolver看起
一个resolver的sendRequest调用的是基类ProtoMessager的sendRequest方法,这个方法其实调用的就是PBSender的sendRequest操作,看PBSender的这个方法的实现
public void sendRequest(PBRequest<PARAM> request, OnPBSenderListener<PARAM> listener){
ALog.i(TAG, "in sendRequest: request=" + request);
request.listener = listener;
request.requestTimeMillis = System.currentTimeMillis();
enqueueRequest(request);
checkForSend(true);
}
看这个方法的两句,第一enqueueRequest,这个是把request放入到mSendQueue这个消息队列里面,第二句checkForSend(true),这个代码最终跑到了startSendRequests,然后就跑到了 sendOutRequestLocked,看实现
private void sendOutRequestLocked(){
PBRequest request;
while ((request = mSendQueue.poll()) != null){
if (request.isCanceled){
ALog.i(TAG, "request already canceled:" + request);
continue;
}
if (!request.isPreviousConnectRequest) {
sendRequestInner(request);
} else { //预留游客模式的情况
boolean isBoundCurrenly = (mLoginState.getAuthType() != null && mLoginState.getAuthType() != AuthType.Tourist);
}
}
}
注意这是一个死循环,到目前为止也就是说,一个PBSender就维护了一个消息队列,自己跑了一个死循环来发送里面的所有请求,而里面每一个请求都会跑sendRequestInner这个方法,看实现
private void sendRequestInner(PBRequest request){
int command = request.command;
int subcmd = request.subcmd;
byte[] payload = request.listener.onBuildRequestData(request, mLoginState);
if (payload == null){
ALog.i(TAG, "onBuildRequestData returned null, request=" + request);
}
ALog.i(TAG, "sendRequestInner: request=" + request);
int timeout = mAuthWaitMillis > 0 ? mAuthWaitMillis : NetworkEngine.DEFAULT_TIMEOUT;
int result = NetworkEngine.shareEngine().sendRequest(command, subcmd, payload, new ProtoBufferMessageHandler(request), timeout);
if (result == -1){
if (request.listener != null)
request.listener.onError(request, ErrorFactoryPb.NETWORK_INVALID);
return;
}
addToWaitList(request);
}
看到这里,一切都豁然开朗了,因为这个时候又出现了NetworkEngine,看这个sendRequest是干了什么