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软件编程有所帮助。

以上是 Android最基本的异步网络请求框架 的全部内容, 来源链接: utcz.com/z/320500.html

回到顶部