欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2024-02-28 16:32:16
 本篇文章我们来一起写一个最基本的android异步网络请求框架,借此来了解下android中网络请求的相关知识。由于个人水平有限,文中难免存在疏忽和谬误,希望大...

 本篇文章我们来一起写一个最基本的android异步网络请求框架,借此来了解下android中网络请求的相关知识。由于个人水平有限,文中难免存在疏忽和谬误,希望大家可以指出,谢谢大家。

1. 同步网络请求

    以http的get请求为例,我们来介绍一下android中一个基本的同步请求框架的实现。直接贴代码:

public class httputils {
 public static byte[] get(string urlstring) {
  httpurlconnection urlconnection = null;
  try {
   url url = new url(urlstring);
   urlconnection = (httpurlconnection) url.openconnection();
   //设置请求方法
   urlconnection.setrequestmethod("get");
   //设置超时时间
   urlconnection.setconnecttimeout(5000);
   urlconnection.setreadtimeout(3000);

   //获取响应的状态码
   int responsecode = urlconnection.getresponsecode();
   if (responsecode == 200) {
    bytearrayoutputstream bos = new bytearrayoutputstream();
    inputstream in = urlconnection.getinputstream();
    byte[] buffer = new byte[4 * 1024];
    int len = -1;
    while((len = in.read(buffer)) != -1) {
     bos.write(buffer, 0, len);
    }
    close(in);
    byte[] result = bos.tobytearray();
    close(bos);
    return result;
   } else {
    return null;
   }
  } catch (exception e) {
   e.printstacktrace();
  } finally {
   if (urlconnection != null) {
    urlconnection.disconnect();
   }
  }

  return null;
 }

 private static void close(closeable stream) {
  if (stream != null) {
   try {
    stream.close();
   } catch (ioexception e) {
    e.printstacktrace();
   }
  }
 }

} 

    相信以上的代码我们大家都不陌生,以上代码就实现了基本的同步网络请求功能,get 方法会返回一个byte[]数组,后续我们可以根据返回的相应类型(文本或图片)对这个字节数组作进一步处理。 

2. 异步网络请求

    通常一个异步http get请求是这样的:发出get方法的调用后,相关任务会在后台线程中自动执行,而我们在主线程中继续处理其他工作,它成功获取get请求的响应时,就会回调onsuccess方法。最直接的写法通常如下所示:

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);
 }
}

以上代码主要就是使用了线程池来达到线程的复用的目的,希望本文所述对大家学习android软件编程有所帮助。