文章純屬個(gè)人學(xué)習(xí)的代碼實(shí)現(xiàn)
網(wǎng)易云微專業(yè)公開課這節(jié)課主要講了如何自己完成一個(gè)簡(jiǎn)易的網(wǎng)絡(luò)請(qǐng)求框架,核心是線程處理和架構(gòu)思想。
我們分析一下整個(gè)架構(gòu)設(shè)計(jì)

首選是 ThreadPoolManager線程池里面有兩個(gè)【永動(dòng)機(jī)】,分別是coreThread和delayThread,他們都有一個(gè) while (true)代碼段,不斷地從隊(duì)列里面獲取請(qǐng)求
可以看看他們的代碼
// 創(chuàng)建核心線程 將隊(duì)列中的請(qǐng)求拿出來 ,交給線程池處理
public Runnable coreThread = new Runnable() {
Runnable runnable = null;
@Override
public void run() {
while (true) {
try {
runnable = mQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
mThreadPoolExecutor.execute(runnable);
}
}
};
public Runnable delayThread = new Runnable() {
HttpTask ht = null;
@Override
public void run() {
while (true) {
try {
ht = mDelay.take();
if (ht.getRetryCount() < 3) {
mThreadPoolExecutor.execute(ht);
ht.setRetryCount(ht.getRetryCount() + 1);
Log.e("===重試機(jī)智===", ht.getRetryCount() + " " + System.currentTimeMillis());
} else {
Log.e("===重試機(jī)智===", "放棄");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
這就能解釋,我們App隨時(shí)都能發(fā)起網(wǎng)絡(luò)請(qǐng)求的原因,因?yàn)樗且粋€(gè)死循環(huán)里面不斷的去隊(duì)列里面取,這樣就能保證每個(gè)請(qǐng)求都能執(zhí)行到。
ThreadPoolManager的核心代碼就是定義兩個(gè)隊(duì)列,一個(gè)線程池,然后執(zhí)行這兩個(gè)線程,具體看看代碼
// 線程安全
private LinkedBlockingQueue<Runnable> mQueue = new LinkedBlockingQueue<>();
private DelayQueue<HttpTask> mDelay = new DelayQueue<>();
//線程池
private ThreadPoolExecutor mThreadPoolExecutor;
private ThreadPoolManager() {
mThreadPoolExecutor = new ThreadPoolExecutor(3, 6, 15,
TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3), new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
//線程沒執(zhí)行成功,返回到這里
addTask(r);
}
});
mThreadPoolExecutor.execute(coreThread);
mThreadPoolExecutor.execute(delayThread);
}
好,分析完整個(gè)驅(qū)動(dòng)部分,我們要去看具體的請(qǐng)求怎么執(zhí)行的
我們直接先看HttpTask它是一個(gè)線程類,主要主要執(zhí)行具體的請(qǐng)求,大概看看
public HttpTask(String url, T requestData, IHttpRequest request, CallbackListener listener) {
this.httpRequest = request;
request.setUrl(url);
request.setListener(listener);
String content = JSON.toJSONString(requestData);
try {
request.setData(content.getBytes("utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
httpRequest.execute();
} catch (Exception e) {
ThreadPoolManager.getInstance().addDelayTask(this);
}
}
這里面其實(shí)包含兩個(gè)部分,一個(gè)是請(qǐng)求部分,請(qǐng)一個(gè)就是請(qǐng)求結(jié)果部分,
請(qǐng)求我們用了IHttpRequest接口進(jìn)行 封裝,請(qǐng)求結(jié)果用 CallbackListener接口進(jìn)行封裝,然后再run()方法開啟請(qǐng)求
這里為啥要用接口呢,第一比如請(qǐng)求,我們每個(gè)請(qǐng)求的url,請(qǐng)求參數(shù),請(qǐng)求返回的數(shù)據(jù)結(jié)果都不一樣,所以我們定義了這些 不同參數(shù)的 入口,如下所示
public interface IHttpRequest {
void setUrl(String url);
void setData(byte[] data);
void setListener(CallbackListener listener);
void execute() throws MalformedURLException;
}
而請(qǐng)求結(jié)果回調(diào)接口CallbackListener我們這么定義
public interface CallbackListener {
void onSuccess(InputStream inputStream);
void onFailure();
}
這樣定義完了 我們看看我們?cè)趺磮?zhí)行一個(gè)真正的請(qǐng)求
NeHttp.sendJsonRequest(url2, null, ResponseClass.class, new IJsonDataListener<ResponseClass>() {
@Override
public void onSuccess(ResponseClass clazz) {
Log.e("==========",clazz.toString());
}
});
這個(gè)NeHttp又是什么,不急先看代碼
public class NeHttp{
public static<T,M> void sendJsonRequest(String url,T requestData,Class<M> reponse,IJsonDataListener listener){
IHttpRequest request=new JsonHttpRequest();
CallbackListener callbackListener=new JsonCallBackListener<>(reponse,listener);
HttpTask ht=new HttpTask(url,requestData,request,callbackListener);
ThreadPoolManager.getInstance().addTask(ht);
}
}
其實(shí)就是封裝一個(gè)真正的請(qǐng)求HttpTask然后加到請(qǐng)求隊(duì)列中ThreadPoolManager.getInstance().addTask(ht);
我們看一下這里是怎么生成一個(gè)真正的HttpTask的
首先 請(qǐng)求部分
IHttpRequest request=new JsonHttpRequest();
其實(shí)就是新建了一個(gè)具體的IHttpRequest實(shí)現(xiàn)類JsonHttpRequest看一下代碼
public class JsonHttpRequest implements IHttpRequest {
private String url;
private byte[] data;
private CallbackListener callbackListener;
private HttpURLConnection urlConn;
@Override
public void setUrl(String url) {
this.url = url;
}
@Override
public void setData(byte[] data) {
this.data = data;
}
@Override
public void setListener(CallbackListener listener) {
this.callbackListener = listener;
}
@Override
public void execute() throws MalformedURLException {
//訪問網(wǎng)絡(luò)
URL url = null;
try {
url = new URL(this.url); // 打開一個(gè)HttpURLConnection連接
urlConn = (HttpURLConnection) url.openConnection();
urlConn.setUseCaches(false);
urlConn.setInstanceFollowRedirects(true);
urlConn.setReadTimeout(3000);
urlConn.setDoInput(true);
urlConn.setDoOutput(true);
urlConn.setRequestMethod("POST");
urlConn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
urlConn.connect();
OutputStream out = urlConn.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(out);
bos.write(data);
bos.flush();
out.close();
bos.close();
if (urlConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream in = urlConn.getInputStream();
callbackListener.onSuccess(in);
} else {
throw new RuntimeException("請(qǐng)求失敗");
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("請(qǐng)求失敗");
} finally {
urlConn.disconnect();
}
}
}
代碼 很長(zhǎng),但是核心在于execute()里面的callbackListener.onSuccess(in);完成請(qǐng)求后回調(diào)這個(gè)接口
當(dāng)然這是Json相關(guān)的請(qǐng)求,所以我們定一個(gè)了一個(gè)CallbackListener callbackListener=new JsonCallBackListener<>(reponse,listener);處理Json數(shù)據(jù)結(jié)果
具體代碼如下
public class JsonCallBackListener<T> implements CallbackListener {
public Class<T> responsClass;
private IJsonDataListener iJsonDataListener;
private Handler mHandler = new Handler(Looper.getMainLooper());
public JsonCallBackListener(Class<T> responsClass, IJsonDataListener jsonDataListener) {
this.responsClass = responsClass;
this.iJsonDataListener = jsonDataListener;
}
@Override
public void onSuccess(InputStream inputStream) {
String response = getContent(inputStream);
final T clazz = JSON.parseObject(response, responsClass);
mHandler.post(new Runnable() {
@Override
public void run() {
iJsonDataListener.onSuccess(clazz);
}
});
}
private String getContent(InputStream inputStream) {
String content = null;
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
System.out.println("Error=" + e.toString());
} finally {
try {
inputStream.close();
} catch (IOException e) {
System.out.println("Error=" + e.toString());
}
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return content;
}
@Override
public void onFailure() {
}
}
核心代碼是這段話
public void onSuccess(InputStream inputStream) {
String response = getContent(inputStream);
final T clazz = JSON.parseObject(response, responsClass);
mHandler.post(new Runnable() {
@Override
public void run() {
iJsonDataListener.onSuccess(clazz);
}
});
}
利用fastJson完成了字符串轉(zhuǎn)具體對(duì)象的操作
然后整個(gè)流程通過iJsonDataListener.onSuccess(clazz);完成了串聯(lián),最后關(guān)于重試那個(gè)大家可以看看代碼 ,思路基本一致,主要通過失敗之后添加到 DelayQue隊(duì)列里面,然后每次都從這個(gè)隊(duì)列重試。
大家想了解更多直接去我的github看代碼實(shí)現(xiàn)