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异步回调的. 在做一个项目的时候,上网看了很多别人的例子,发现都没有一个简单的,方便的异步请求的封装例子.我这里要给出的封装代码,是异 ... 
随机推荐
- Mac OS X 快捷键
			启动快捷键 按下按键或组合键,直到所需的功能出现(例如,在启动过程中按住 Option 直到出现“启动管理程序”,或按住 Shift 直到出现“安全启动”).提示:如果启动功能未起作用,而您使用的是第 ... 
- 03_汇编语言(n个数找最大值)
			程序要求: 先输入一个数n(0<n<=100),再输入n个无符号数K(0<=K<=65535),找出这n个数的最大值并输出 测试实例保证输入每个数之后,都会以回车结束 代码: ... 
- ArcGis 10+Oracle发布WFS-T服务,无法更新Feature的解决方法
			现象: 前端采用Openlayers,更新Feature时服务器端返回的XML提示更新错误 原因: 参考:http://support.esri.com/en/knowledgebase/techar ... 
- 绘制复数图形和双y轴图形
			clearclct=0:0.1:2*pi;x=sin(t);y=cos(t);z=x+i*y;subplot(1,3,1)plot(t,z,'r') %注:这种方式下,不论参数t,z哪个是复数,都将忽 ... 
- Hive tuning tips
			1. limit Hive has a configuration property to enable sampling of source data for use with LIMIT: hiv ... 
- Canvas修行之黑客帝国代码雨
			既然是修行,不卖弄关子,不吊胃口,修行成果必须先晒一晒. 下图是我用canvas画的黑客帝国代码雨,想起当年看黑客帝国时,那个代码雨场景让我心旷神怡,大开脑洞,满脑子是那种三维空间,无数0和1像雨一样 ... 
- DAC使用基本准则
			DAC Nyquist Zones, Zero Order Hold, and Images why do the Fout images exist in every Nyquist zone? W ... 
- win8程序开机自启动管理
			主要介绍利用系统自身的工具来管理开机自启动,而非第三方的工具,自己了解了,也写出来分享给大家@.·.@ 1.程序设置开机自启动 a. 打开计算机资源管理器-->进入"C:\Progra ... 
- CSS设置滚动条样式
			因为在现在的大部分项目中很多都用到了滚动条,有时候用到模拟的滚动条,现在说下滚动条的CSS也能解决. 比如网易邮箱的滚动条样子很好看,就是利用的CSS来设置的,而且是webkit浏览器的.如图所示: ... 
- 2014 Super Training #7 B Continuous Login --二分
			原题:ZOJ 3768 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3768 一个结论:一个正整数总能用不超过三个前n项相 ... 
