網(wǎng)易云微專業(yè)安卓-如何一步步打造自己的網(wǎng)絡(luò)訪問框架

文章純屬個(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ì)

image.png

首選是 ThreadPoolManager線程池里面有兩個(gè)【永動(dòng)機(jī)】,分別是coreThreaddelayThread,他們都有一個(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)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容