網(wǎng)絡(luò)架構(gòu)之自定義Valloy

應(yīng)用到知識點

  • 需求:
    支持請求 JSON文本類型瓤逼,音頻,圖片類型,批量下載。上傳
    請求各種 數(shù)據(jù)時芽死,調(diào)用層不關(guān)心上傳參數(shù)分裝,如(request.addParamas(key,value))
    直接將參數(shù)分裝成對象次洼,傳給框架
    獲取數(shù)據(jù)后 調(diào)用層不關(guān)心JSON數(shù)據(jù)解析
    回調(diào)時 調(diào)用層只需要知道傳入的JSON的對應(yīng)的響應(yīng)類关贵。
    回調(diào)響應(yīng)結(jié)果發(fā)生在主線程(線程切換)
    對下載,上傳擴展
    支持高并發(fā)請求卖毁,請求隊列依次獲取揖曾,可以設(shè)置最大并發(fā)數(shù),設(shè)置先請求先執(zhí)

  • 會用到的知識點
    泛型
    請求隊列
    阻塞隊列
    線程池拒絕策略
  • 設(shè)計模式
    模板方法模式
    單例模式
    策略模式
    生產(chǎn)者消費者模式
Paste_Image.png

流程步驟

1亥啦、客戶端請求

 public void login(View view) {
        User user = new User();
        user.setName("13343491234");
        user.setPassword("123456");
        for (int i = 0; i < 50; i++) {
            Volley.sendRequest(user, url, LoginRespense.class, new 
IDataListener<LoginRespense>() {
                @Override
                public void onSuccess(LoginRespense loginRespense) {
                    Log.i(TAG, loginRespense.toString());
                }

                @Override
                public void onFail() {
                    Log.i(TAG, "獲取失敗");
                }
            });
        }
    }

2炭剪、封裝請求參數(shù)并添加任務(wù)到線程池

請求參數(shù)


public class Volley {
    /**
     * @param <T> 請求參數(shù)類型
     * @param <M> 響應(yīng)參數(shù)類型
     *            暴露給調(diào)用層
     */
   public static <T, M> void sendRequest(T requestInfo, String url,
                                          Class<M> response, IDataListener dataListener) {
        RequestHodler<T> requestHodler = new RequestHodler<>();
        requestHodler.setUrl(url);
        //執(zhí)行http接口實現(xiàn)類
        IHttpService httpService = new JsonHttpService();
        //回調(diào)接口
        IHttpListener httpListener = new JsonDealLitener<>(response, dataListener);
        requestHodler.setHttpService(httpService);
        requestHodler.setHttpListener(httpListener);
        HttpTask<T> httpTask = new HttpTask<>(requestHodler);
        try {
            ThreadPoolManager.getInstance().execte(new FutureTask<Object>(httpTask, null));
        } catch (InterruptedException e) {
            dataListener.onFail();
        }
    }

3、線程池管理任務(wù)

將任務(wù)添加到線程池翔脱,這里用戶到了阻塞隊列實現(xiàn)高并發(fā)奴拦。

public class ThreadPoolManager {
    private static final String TAG = "ThreadPoolManager";
    private static ThreadPoolManager instance = new ThreadPoolManager();
    //阻塞隊列
    private LinkedBlockingQueue<Future<?>> taskQuene = new LinkedBlockingQueue<>();

    //線程池類,添加FutureTask任務(wù)
    private ThreadPoolExecutor threadPoolExecutor;

    public static ThreadPoolManager getInstance() {
        return instance;
    }

    private ThreadPoolManager() {
        threadPoolExecutor = new ThreadPoolExecutor(4, 10, 10, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(4), handler);
        threadPoolExecutor.execute(runable);
    }


    private Runnable runable = new Runnable() {
        @Override
        public void run() {
            while (true) {
                FutureTask futrueTask = null;
                try {
                    /**
                     * 阻塞式函數(shù)
                     */
                    Log.i(TAG, "等待隊列     " + taskQuene.size());
                    futrueTask = (FutureTask) taskQuene.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (futrueTask != null) {
                    threadPoolExecutor.execute(futrueTask);
                }
                Log.i(TAG, "線程池大小      " + threadPoolExecutor.getPoolSize());
            }
        }
    };

    public <T> void execte(FutureTask<T> futureTask) throws InterruptedException {
        taskQuene.put(futureTask);
    }

    //當(dāng)線程池滿的時候回調(diào)用RejectedExecutionHandler類的rejectedExecution方法届吁,將任務(wù)添加的任務(wù)隊列
    private RejectedExecutionHandler handler = new RejectedExecutionHandler() {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            try {
                taskQuene.put(new FutureTask<Object>(r, null) {
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
}

4错妖、網(wǎng)絡(luò)請求和響應(yīng)

第三步將任務(wù)HttpTask添加到線程池中隶糕,該類的網(wǎng)絡(luò)請求及響應(yīng)的接口分別是IHttpServiceIHttpListener。前者用于執(zhí)行網(wǎng)絡(luò)請求站玄,后者用于處理響應(yīng)并且將響應(yīng)信息回傳給調(diào)用者枚驻。

  • 網(wǎng)絡(luò)請求
public class JsonHttpService implements IHttpService {
    private IHttpListener httpListener;

    private HttpClient httpClient=new DefaultHttpClient();
    private HttpPost httpPost;
    private String url;

    private byte[] requestDate;
    /**
     * httpClient獲取網(wǎng)絡(luò)的回調(diào)
     */
    private HttpRespnceHandler httpRespnceHandler=new HttpRespnceHandler();
    @Override
    public void setUrl(String url) {
        this.url=url;
    }

    @Override
    public void excute() {
        httpPost=new HttpPost(url);
        ByteArrayEntity byteArrayEntity=new ByteArrayEntity(requestDate);
        httpPost.setEntity(byteArrayEntity);
        try {
            httpClient.execute(httpPost,httpRespnceHandler);
        } catch (IOException e) {
            httpListener.onFail();
        }
    }

    @Override
    public void setHttpListener(IHttpListener httpListener) {
        this.httpListener=httpListener;
    }

    @Override
    public void setRequestData(byte[] requestData) {
         this.requestDate=requestData;
    }
    private class HttpRespnceHandler extends BasicResponseHandler
    {
        @Override
        public String handleResponse(HttpResponse response) 
throws ClientProtocolException {
            //響應(yīng)嗎
            int code=response.getStatusLine().getStatusCode();
            if(code==200)
            {
                httpListener.onSuccess(response.getEntity());
            }else
            {
                httpListener.onFail();
            }


            return null;
        }
    }
}
  • 網(wǎng)絡(luò)響應(yīng)
    由于任務(wù)執(zhí)行是在子線程,調(diào)用者(Activity)一般在主線程更新UI株旷,所以要進行線程切換再登。這里要使用主線程的Handler,通過post方法執(zhí)行客戶端回調(diào)接口IDataListener進行數(shù)據(jù)傳遞晾剖。
public class JsonDealLitener<M> implements IHttpListener {
    private Class<M> responese;
    /**
     * 回調(diào)調(diào)用層 的接口
     */
    private IDataListener<M> dataListener;

    Handler handler=new Handler(Looper.getMainLooper());
    public JsonDealLitener(Class<M> responese, IDataListener<M> dataListener) {
        this.responese = responese;
        this.dataListener = dataListener;
    }

    @Override
    public void onSuccess(HttpEntity httpEntity) {
        InputStream inputStream=null;
        try {
            inputStream=httpEntity.getContent();
            /*
            得到網(wǎng)絡(luò)返回的數(shù)據(jù)
            子線程
             */
            String content=getContent(inputStream);
            final M m= JSON.parseObject(content,responese);

            handler.post(new Runnable() {
                @Override
                public void run() {
                    dataListener.onSuccess(m);
                }
            });
        } catch (IOException e) {
            dataListener.onFail();
        }

    }

    @Override
    public void onFail() {
        dataListener.onFail();
    }
    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) {
                dataListener.onFail();
                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();
            dataListener.onFail();
        }
        return content;
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锉矢,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子齿尽,更是在濱河造成了極大的恐慌沽损,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件循头,死亡現(xiàn)場離奇詭異绵估,居然都是意外死亡,警方通過查閱死者的電腦和手機卡骂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門国裳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人全跨,你說我怎么就攤上這事缝左。” “怎么了浓若?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵渺杉,是天一觀的道長。 經(jīng)常有香客問我挪钓,道長是越,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任诵原,我火速辦了婚禮英妓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘绍赛。我一直安慰自己蔓纠,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布吗蚌。 她就那樣靜靜地躺著腿倚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蚯妇。 梳的紋絲不亂的頭發(fā)上敷燎,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天暂筝,我揣著相機與錄音,去河邊找鬼硬贯。 笑死焕襟,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的饭豹。 我是一名探鬼主播鸵赖,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼拄衰!你這毒婦竟也來了它褪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤翘悉,失蹤者是張志新(化名)和其女友劉穎茫打,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體妖混,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡老赤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了源葫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诗越。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖息堂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情块促,我是刑警寧澤荣堰,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站竭翠,受9級特大地震影響振坚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜斋扰,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一渡八、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧传货,春花似錦屎鳍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至粮宛,卻和暖如春窥淆,著一層夾襖步出監(jiān)牢的瞬間卖宠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工忧饭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留扛伍,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓词裤,卻偏偏與公主長得像蜒秤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子亚斋,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理作媚,服務(wù)發(fā)現(xiàn),斷路器帅刊,智...
    卡卡羅2017閱讀 134,599評論 18 139
  • 從哪說起呢纸泡? 單純講多線程編程真的不知道從哪下嘴。赖瞒。 不如我直接引用一個最簡單的問題女揭,以這個作為切入點好了 在ma...
    Mr_Baymax閱讀 2,734評論 1 17
  • AFHTTPRequestOperationManager 網(wǎng)絡(luò)傳輸協(xié)議UDP、TCP栏饮、Http吧兔、Socket、X...
    Carden閱讀 4,319評論 0 12
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,498評論 25 707
  • 我本來是想在宿舍里睡覺的袍嬉,但我還得去安排運動會的事情境蔼。學(xué)校最近一直在忙這個事情,很煩的伺通。 為了照顧一些外來的運動選...
    愛夢的我閱讀 124評論 0 0