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 onSuccess(byte[] 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);
}
}
以上代码主要就是使用了线程池来达到线程的复用的目的,关于线程池的更加深入详细的介绍,大家可以看这里:深入理解Java之线程池
3. 参考资料
Android docs
Android中的异步网络请求的更多相关文章
- IOS9中使用NSURLConection发送异步网络请求
IOS9中使用NSURLConection发送异步网络请求 在ios9中,NSURLConection的sendSync..和sendAsync已经过时.被NSURLSession代替. 以下蓝色部分 ...
- Android中AsyncTask异步
今天我们学习了 AsyncTack, 这是一个异步任务. 那么这个异步任务可以干什么呢? 因为只有UI线程,即主线程可以对控件进行更新操作.好处是保证UI稳定性,避免多线程对UI同时操作. 同时要把耗 ...
- Android探索之HttpURLConnection网络请求
前言: 最近一直想着学习一下比较好的开源网络框架okhttp,想着学习之前还是先总结一下Android原生提供的网络请求.之前一直在使用HttpClient,但是android 6.0(api 23) ...
- iOS 多个异步网络请求全部返回后再执行具体逻辑的方法
对于dispatch多个异步操作后的同步方法,以前只看过dispatch_group_async,看看这个方法的说明: * @discussion * Submits a block to a dis ...
- AJAX其实就是一个异步网络请求
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML).其实就是一个异步网络请求. 一.创建对象 var xmlhttp; if (w ...
- Android Asynchronous Http Client-Android异步网络请求客户端接口
1.简介 Android中网络请求一般使用Apache HTTP Client或者采用HttpURLConnect,但是直接使用这两个类库需要写大量的代码才能完成网络post和get请求,而使用and ...
- Android之封装好的异步网络请求框架
1.简介 Android中网络请求一般使用Apache HTTP Client或者采用HttpURLConnection,但是直接使用这两个类库需要写大量的代码才能完成网络post和get请求,而使 ...
- Android中android-async-http开源网络框架的简单使用
android-async-http开源网络框架是专门针对Android在Apache的基础上构建的异步且基于回调的http client.所有的请求全在UI线程之外发生,而callback发生在创建 ...
- iOS开发——post异步网络请求封装
IOS中有许多网络请求的函数,同步的,异步的,通过delegate异步回调的. 在做一个项目的时候,上网看了很多别人的例子,发现都没有一个简单的,方便的异步请求的封装例子.我这里要给出的封装代码,是异 ...
随机推荐
- INFORMATICA 的调优之 INFORMATICA SERVER TUNING
INFORMATICA SERVER的调优我认为主要从两个级别来做,一个是MAPPING级别,一个是SESSION级别. 对于MAPPING级别的调优: 一 对MAPPING数据流向的优化: 1 控 ...
- 人生导师——如何学习C++的Windows方向
原来发在百度上,今天被人挖坟挖出来了,我就再贴出来吧. -----------------------有什么说的不对的地方---------------------- 本文原创,转载请注明出处并保持文 ...
- PL/SQL之--游标
一.游标简介 在PL/SQL中执行SELECT.INSERT.DELETE和UPDATE语句时,ORACLE会在内存中为其分配上下文区(Context Area),也称为缓冲区.游标是指向该区的一个指 ...
- cocos2d-x之多个移动的小球
MoveBalls.hpp: #ifndef MoveBalls_hpp #define MoveBalls_hpp #include <stdio.h> #include "c ...
- C++类所占内存大小计算
C++类所占内存大小计算 说明:笔者的操作系统是32位的. class A {}; sizeof( A ) = ? sizeof( A ) = 1明明是空类,为什么编译器说它是1呢? 空类同样可以实例 ...
- 09_Sum游戏(UVa 10891 Game of Sum)
问题来源:刘汝佳<算法竞赛入门经典--训练指南> P67 例题28: 问题描述:有一个长度为n的整数序列,两个游戏者A和B轮流取数,A先取,每次可以从左端或者右端取一个或多个数,但不能两端 ...
- STL的erase()陷阱-迭代器失效总结
下面材料整理自Internet&著作. STL中的容器按存储方式分为两类,一类是按以数组形式存储的容器(如:vector .deque):另一类是以不连续的节点形式存储的容器(如:list.s ...
- [转]Oracle分页之三:利用PagerView来实现无刷新GridView
本文转自:http://www.cnblogs.com/scy251147/archive/2011/04/16/2018355.html 接上面一节,上面还存在问题就是分页控件使用的仍然是服务器端控 ...
- Web安全--XSS现代WAF规则探测及绕过技术
XSS现代WAF规则探测及绕过技术初始测试 1.使用无害的payload,类似<b>,<i>,<u>观察响应,判断应用程序是否被HTML编码,是否标签被过滤,是否过 ...
- HTML meta viewport属性详解
什么是Viewport 手机浏览器是把页面放在一个虚拟的“窗口”(viewport)中,通常这个虚拟的“窗口”(viewport)比屏幕宽,这样就不用把每个网页挤到很小的窗口中(这样会破坏没有针对手机 ...