Android最基本的异步网络请求框架

2019-12-10 18:15:57刘景俊

public class AsyncHttpUtils {public static byte[] get(String url, ResponseHandler handler) {
  final Handler mHandler = new Handler();
  new Thread(new Runnable() {
   @Override
   public void run() {
    final byte[] result = HttpUtils.get(url);
    handler.post(new Runnable() {
     @Override
     public void run() {
      responseHandler.onSuccess(result);
     }
    });
   }
  });
 }
} 

       其中,ResponseHandler接口的定义如下:

public interface ResponseHandler {
 void onSucess(bytep[] result);
}
 

    我们可以看到,以上实现异步GET请求的代码很直截了当,然而存在着以下问题:每次请求时都会创建一个线程,这样当请求比较频繁的情况下会创建大量大线程,这样的话创建、销毁线程以及线程调度的开销会很大。而且Thread对象是一个匿名内部类对象,会隐式持有外围类引用,可能会引起Memory Leak。

    针对以上问题,我们可以使用线程池来复用线程,以避免不必要的创建及销毁线程的开销,改进后AsyncHttpUtils类的代码如下:

public class AsyncHttpUtils {
 //获取当前设备的CPU数
 public static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
 //核心池大小设为CPU数加1
 private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
 //设置线程池的最大大小
 private static final int MAX_POOL_SIZE = 2 * CPU_COUNT + 1;
 //存活时间
 private static final long KEEP_ALIVE = 5L;
 
 //创建线程池对象
 public static final Executor threadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
   MAX_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());

 public static void get(final String url, final ResponseHandler responseHandler) {
  final Handler mHandler = new Handler(Looper.getMainLooper());
  
  //创建一个新的请求任务
  Runnable requestRunnable = new Runnable() {
   @Override
   public void run() {
    final byte[] result = HttpUtils.get(url);
    if (result != null) {
     mHandler.post(new Runnable() {
      @Override
      public void run() {
       //result不为空表明请求成功,回调onSuccess方法
       responseHandler.onSuccess(result);
      }
     });
    }
   }
  };
  threadPoolExecutor.execute(requestRunnable);
 }
}