<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      安卓筆記俠

      專注安卓開發

      導航

      Volley手寫屬于自己的萬能網絡訪問框架

      用戶在調用層(Activity或Service中),發起一個網絡請求,該請求肯定包含url,請求參數(requestParameter),以及我們需要給調用層提供一個請求成功或失敗以后回調監聽的接口dataListener(這一點與Volley類似)。

      在框架層,每一次用戶請求可以看做一個Http任務,這些任務我們可以用一個請求隊列存儲起來,框架工作時不斷地從請求隊列中取出任務放到處理中心中,處理中心是一個線程池ThreadPool。使用線程池可以帶來3個好處: 
      1.降低資源消耗:通過重用已經創建的線程來降低線程創建和銷毀的消耗 
      2.提高響應速度:任務到達時不需要等待線程創建就可以立即執行。 
      3.提高線程的可管理性:線程池可以統一管理、分配、調優和監控。

      由于用戶請求的數量是不確定的,所以請求隊列的長度應該沒有限制,所以這里的數據結構,我們應該使用鏈表。正好,java給我們提供了一個阻塞式隊列LinkedBlockingQueue,它是一個單向鏈表實現的無界阻塞隊列,先進先出,支持多線程并發操作。

      再仔細考慮一下框架層的操作,用戶不斷發請求產生HttpTask,處理中心不斷從請求隊列中去任務,這和那個生產者消費者模式是不是很像?所以我們還需要考慮并發和同步問題,而LinkedBlockingQueue是線程安全的,實現了先進先出等特性,是作為生產者消費者的首選。LinkedBlockingQueue 可以指定隊列的容量,也可以不指定,不指定的話,默認最大是Integer.MAX_VALUE,其中主要用到put和take方法,put方法在隊列滿的時候會阻塞直到有隊列成員被消費,take方法在隊列空的時候會阻塞,直到有隊列成員被放進來。

      至于處理中心的線程池,我們使用jdk里的ThreadPoolExecutor,具體用法可以自行百度,唯一需要注意的就是其中的拒絕策略。

      代碼編寫

      首先,我們需要一個線程池的管理類,來管理請求隊列和處理中心處理任務。由于系統中僅有一個線程池管理的類,所以該類應該設計成單例模式

      ThreadPoolManager.java

      import java.util.concurrent.ArrayBlockingQueue;
      import java.util.concurrent.LinkedBlockingQueue;
      import java.util.concurrent.RejectedExecutionHandler;
      import java.util.concurrent.ThreadPoolExecutor;
      import java.util.concurrent.TimeUnit;
      
      /**
       1.  線程池管理類
       */
      public class ThreadPoolManager {
          //1.將請求任務放到請求隊列中
          //通過阻塞式隊列來存儲任務
          private LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
          //添加任務
          public void execute( Runnable runnable ){
              if( runnable != null ) {
                  try {
                      queue.put(runnable);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
          }
          //2.把隊列中的任務放到線程池
          private ThreadPoolExecutor threadPoolExecutor ;
          private ThreadPoolManager(){
              threadPoolExecutor = new ThreadPoolExecutor(4,20,15, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(4),rejectedExecutionHandler);
              //運行線程池
              threadPoolExecutor.execute(runnable);
          }
          //當線程數超過maxPoolSize或者keep-alive時間超時時執行拒絕策略
          private RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() {
              /**
               * @param runnable 超時被線程池拋棄的線程
               * @param threadPoolExecutor
               */
              @Override
              public void rejectedExecution(Runnable runnable, ThreadPoolExecutor threadPoolExecutor) {
                  //將該線程重新放入請求隊列中
                  try {
                      queue.put(runnable);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
      
              }
          };
          //3.讓他們開始工作起來
          //整個的工作線程
          private Runnable runnable = new Runnable() {
              @Override
              public void run() {
                  while(true){
                      Runnable runnable = null ;
                      //不斷從從請求隊列中取出請求
                      try {
                          runnable = queue.take();
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      //如果不為空,放入線程池中執行
                      if( runnable != null ){
                          threadPoolExecutor.execute(runnable);
                      }
                  }
      
              }
          };
      
          //單例模式
          private static ThreadPoolManager singleInstance = new ThreadPoolManager();
          public static ThreadPoolManager getSingleIntance(){
              return singleInstance;
          }
      }

      接下來我們需要將寫兩個接口將用戶的網絡訪問操作分成兩部分(參考架構圖),一個是請求(IHttpRequest),一個是響應(IHttpListener), 
      在請求接口中,我們需要做的事有三個

      1. 設置url
      2. 設置請求參數
      3. 執行請求

      IHttpRequest.java

      /**
       * 封裝請求
       */
      public interface IHttpRequest {
          void setUrl(String url);
          void setRequestData( byte[] requestData );
          void execute();
          //需要設置請求和響應兩個接口之間的關系
          void setHttpCallBack( IHttpListener httpListener );
      }

      在響應接口中,我們需要做的事也很簡單

      1. 處理結果
      2. 回調應用層

      IHttpListener.java

      import java.io.InputStream;
      
      /**
       * 封裝響應
       */
      public interface IHttpListener {
          //接受上一個接口的結果
          void onSuccess(InputStream inputStream);
          void onFailure();
      }

      接下來我們編寫代表請求任務的類HttpTask,讓它實現Runnable接口,并且維護IHttpRequest和IHttpListener兩個接口的引用,在HttpTask的構造方法中,進行一些初始化操作,設置請求的url,請求參數,設置監聽器等等。在將請求參數對象轉換成字符串的過程中,我們使用了阿里的fastjson這個jar包。最后在run方法中,執行httpRequest的請求。另外注意這里泛型的使用。

      HttpTask.java

      import com.alibaba.fastjson.JSON;
      
      import java.io.UnsupportedEncodingException;
      
      
      public class HttpTask<T> implements Runnable {
          private IHttpRequest httpRequest;
          private IHttpListener httpListener;
          public<T> HttpTask( T requestInfo , String url , IHttpRequest httpRequest, IHttpListener httpListener){
              this.httpRequest = httpRequest;
              this.httpListener = httpListener;
              //設置url
              this.httpRequest.setUrl(url);
              //設置響應回調
              this.httpRequest.setHttpCallBack(httpListener);
              //設置請求參數
              if( requestInfo != null ){
                  //將用戶發送的請求參數對象轉換成字符串
                  String requestContent = JSON.toJSONString(requestInfo);
                  //字符串轉byte數組
                  try {
                      this.httpRequest.setRequestData(requestContent.getBytes("utf-8"));
                  } catch (UnsupportedEncodingException e) {
                      e.printStackTrace();
                  }
              }
      
          }
          @Override
          public void run() {
              httpRequest.execute();
          }
      }

      接下來我們編寫IHttpRequest的實現類,JsonHttpRequest , 在重寫的execute方法中,使用原生的HttpURLConnection執行網絡請求,請求成功后,回調IHttpListener的onSuccess方法。

      如果想要傳送其他數據(圖片,文件等),同樣實現IHttpRequest該接口即可,所以這個框架的擴展性十分良好。

      JsonHttpRequest.java

      import java.io.BufferedOutputStream;
      import java.io.InputStream;
      import java.io.OutputStream;
      import java.net.HttpURLConnection;
      import java.net.URL;
      
      /**
       * Json版Http請求
       */
      
      public class JsonHttpRequest implements IHttpRequest{
      
          private String url ;
          private byte[] requestData ;
          private IHttpListener httpListener;
      
          @Override
          public void setUrl(String url) {
              this.url = url ;
          }
      
          @Override
          public void setRequestData(byte[] requestData) {
              this.requestData = requestData;
          }
      
          //原生的網絡操作在這里實現
          @Override
          public void execute() {
              httpUrlconnPost();
          }
      
          private HttpURLConnection urlConnection = null ;
      
          public void httpUrlconnPost(){
              URL url = null;
              try{
                  url = new URL(this.url);
                  //打開http連接
                  urlConnection = (HttpURLConnection) url.openConnection();
                  //設置連接的超時時間
                  urlConnection.setConnectTimeout(6000);
                  //不使用緩存
                  urlConnection.setUseCaches(false);
                  urlConnection.setInstanceFollowRedirects(true);
                  //響應的超時時間
                  urlConnection.setReadTimeout(3000);
                  //設置這個連接是否可以寫入數據
                  urlConnection.setDoInput(true);
                  //設置這個連接是否可以輸出數據
                  urlConnection.setDoOutput(true);
                  //設置請求的方式
                  urlConnection.setRequestMethod("POST");
                  urlConnection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
                  urlConnection.connect();
      
                  //使用字節流發送數據
                  OutputStream out = urlConnection.getOutputStream();
                  BufferedOutputStream bos = new BufferedOutputStream(out);
                  if( requestData != null ){
                      //把字節數組的數據寫入緩沖區
                      bos.write(requestData);
                  }
                  //刷新緩沖區,發送數據
                  bos.flush();
                  out.close();
                  bos.close();
      
                  //獲得服務器響應
                  if( urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK){
                      InputStream in = urlConnection.getInputStream();
                      //回調監聽器的listener方法
                      httpListener.onSuccess(in);
                  }
              }catch ( Exception e){
                  e.printStackTrace();
              }
          }
      
          @Override
          public void setHttpCallBack(IHttpListener httpListener) {
              this.httpListener = httpListener;
          }
      }

      接下來是IHttpListener的Json版本實現類,在該類中要注意的事就是回調結果給用戶時要進行線程的切換(使用Handler),并且要將返回的json字符串轉換成泛型對象(該對象由用戶自定義)。

      JsonHttpListener.java

      import android.os.Handler;
      import android.os.Looper;
      
      import com.alibaba.fastjson.JSON;
      
      import java.io.BufferedReader;
      import java.io.IOException;
      import java.io.InputStream;
      import java.io.InputStreamReader;
      
      /**
       * Json版本的httpListener
       */
      
      public class JsonHttpListener<M> implements IHttpListener{
          Class<M> responseClass;
          private IDataListener<M> dataListener;
      
          public JsonHttpListener(Class<M> responseClass, IDataListener<M> dataListener) {
              this.responseClass = responseClass;
              this.dataListener = dataListener;
          }
      
          //用于切換線程
          Handler handler = new Handler(Looper.getMainLooper());
          @Override
          public void onSuccess(InputStream inputStream) {
              //獲取響應結果,把byte數據轉換成String數據
              String content = getContent(inputStream);
              //將json字符串轉換成對象
              final M response = JSON.parseObject(content,responseClass);
              //把結果傳送到調用層
              handler.post(new Runnable() {
                  @Override
                  public void run() {
                      if( dataListener != null ){
                          dataListener.onSuccess(response);
                      }
      
                  }
              });
      
          }
      
          @Override
          public void onFailure() {
              handler.post(new Runnable() {
                  @Override
                  public void run() {
                      if( dataListener != null ){
                          dataListener.onFailure();
                      }
      
                  }
              });
      
          }
      
          /**
           * 將流轉換成字符串
           * @param inputStream
           * @return
           */
          private String getContent(InputStream inputStream){
              String content = null ;
              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 ){
                  e.printStackTrace();
              }finally {
                  try {
                      inputStream.close();
                      reader.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
              return sb.toString();
          }
      }

      最后兩步

      1. 請求成功后,返回結果給調用層時,我們還要寫一個數據返回的統一接口IDataListener來給用戶使用(跟Volley一樣)
      2. 不能讓用戶自己去創建HttpTask,用戶請求也需要一個統一接口。

      這樣我們框架的封裝性會更好。

      IDataListener.java

      /**
       * 回調調用層的接口,數據返回的統一接口
       */
      
      public interface IDataListener<M> {
          void onSuccess( M m );
          void onFailure();
      }

      Volley.java

      /**
       * 用戶請求的統一接口
       */
      public class Volley {
          public static<T,M> void sendJsonRequest( T requestInfo , String url , Class<M> response , IDataListener<M> dataListener){
              IHttpRequest httpRequest = new JsonHttpRequest();
              IHttpListener httpListener = new JsonHttpListener<>(response,dataListener);
              HttpTask<T> httpTask = new HttpTask<T>(requestInfo,url,httpRequest,httpListener);
              ThreadPoolManager.getSingleIntance().execute(httpTask);
          }
      }

      最后在MainActivity中測試

      public void onClick(View view) {
                      //Student為自己定義的javaBean
                      Volley.sendJsonRequest(null, url, Student.class, new IDataListener<Student>() {
                          @Override
                          public void onSuccess(Student student) {
                              Toast.makeText(MainActivity.this,student.getName(),Toast.LENGTH_SHORT).show();
                          }
      
                          @Override
                          public void onFailure() {
                              Toast.makeText(MainActivity.this,"請求失敗",Toast.LENGTH_SHORT).show();
                          }
                      });
                  }

      想要拓展更多的功能,請求更多類型的數據,我們只需要實現IHttpRequest和IHttpListener這兩個接口就行了。

       

      參考:https://www.jianshu.com/p/396ada3885cc

      posted on 2018-05-24 15:11  安卓筆記俠  閱讀(899)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 中文字幕久久人妻熟人妻| 大方县| 狠狠躁天天躁中文字幕无码| 亚洲国产成人自拍视频网| 一本色道久久加勒比综合| 午夜激情小视频一区二区| 日本偷拍自影像视频久久| 人妻少妇久久中文字幕| 成人免费A级毛片无码片2022 | 成人3d动漫一区二区三区| 中文字幕国产精品资源| 欧美裸体xxxx极品| 国产一区二区三区美女| 日韩精品一区二区三区无| 97se亚洲综合自在线| 国产欧美另类久久久精品不卡| 国产一区二区高清不卡| 隔壁老王国产在线精品| 国产精品综合色区在线观| 久久99国产精品尤物| 亚洲欧美一区二区三区在线| 日韩精品视频一二三四区| 国产美女MM131爽爽爽| 勃利县| 欧美日韩亚洲国产| 亚洲AV蜜桃永久无码精品 | 免费看视频的网站| 国产蜜臀久久av一区二区| 国产极品粉嫩福利姬萌白酱| 91亚洲国产三上悠亚在线播放| 夜夜春久久天堂亚洲精品| V一区无码内射国产| 亚洲国产日韩一区三区| 99精品久久免费精品久久| 亚洲精品www久久久久久| 亚洲 欧美 唯美 国产 伦 综合| 日本一区二区三区视频一| 日本中文字幕有码在线视频 | 夏河县| 激情四射激情五月综合网| 国产成AV人片久青草影院|