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

以上代码主要就是使用了线程池来达到线程的复用的目的,关于线程池的更加深入详细的介绍,大家可以看这里:深入理解Java之线程池

3. 参考资料

Android docs

时间: 2024-10-14 11:25:18

Android中的异步网络请求的相关文章

Github 上Top1的Android 异步网络请求框架

今天给大家分享一个github上Top1的Android异步网络请求框架的使用方法,我给大家分享一个它的基本用法. 先来一个简单的get请求 AsyncHttpClient client = new AsyncHttpClient(); client.get("http://www.google.com", new AsyncHttpResponseHandler() { @Override public void onStart() { // called before reques

iOS NSURLConnection和异步网络请求

在日常应用中,我们往往使用AFNetworking等第三方库来实现网络请求部分.这篇文章会简要地介绍一下如何使用NSURLConnection来进行异步的网络请求. 我们先看一个小demo - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSString *urlStr = @"http://www.baidu.c

Android 中的异步下载

网上提到最多的就是利用AsyncTask进行异步下载,用android-async-http第三方库的也比较多.这里写点注意事项. 先说说android-async-http,这个库发送请求利用threadpool,也就是不在主线程做发送了,但是需要注意的是,如果你在主线程调用发送函数,发送是不在主线程中了,但是回调函数还是在主线程中的(因为处理回调的handler默认会建立在调用线程中)!这一点要注意!如果你的回调函数比较复杂,就会影响UI的使用!这种情况,推荐使用AsyncTask,在Asy

Android探索之HttpURLConnection网络请求

前言: 最近一直想着学习一下比较好的开源网络框架okhttp,想着学习之前还是先总结一下Android原生提供的网络请求.之前一直在使用HttpClient,但是android 6.0(api 23) SDK,不再提供org.apache.http.*(只保留几个类).所以我们今天主要总结HttpURLConnection的使用. HttpURLConnection介绍: HttpURLConnection是一种多用途.轻量极的HTTP客户端,使用它来进行HTTP操作可以适用于大多数的应用程序.

Android中ListView异步加载图片错位、重复、闪烁问题分析及解决方案

Android中ListView异步加载图片错位.重复.闪烁问题分析及解决方案 我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图片错位.重复.闪烁等问题,其实这些问题总结起来就是一个问题,我们需要对这些问题进行ListView的优化. 比如ListView上有100个Item,一屏只显示10个Item,我们知道getView()中convertView是用来复用View对象的,因为一个Item的对应一个View对象,而ImageView控件就是View对象通

Android之封装好的异步网络请求框架

1.简介 Android中网络请求一般使用Apache HTTP Client或者采用HttpURLConnection,但是直接使用这两个类库需要写大量的代码才能完成网络post和get请求,而使用这个MyHttpUtils库可以大大的简化操作,它是基于HttpURLConnection,所有的请求都是独立在UI主线程之外,没有通过CommCallback回调方法处理请求结果, 没有了子线程.没有了handle,链式的变成使得代码更加清晰 . 2.特性 支持get.post请求,文件下载,上传

浅谈Android中的异步加载之ListView中图片的缓存及优化三

     隔了很久没写博客,现在必须快速脉动回来.今天我还是接着上一个多线程中的异步加载系列中的最后一个使用异步加载实现ListView中的图片缓存及其优化.具体来说这次是一个综合Demo.但是个人觉得里面还算有点价值的就是里面的图片的缓存的实现.因为老实说它确实能在实际的项目中得到很好的应用.主要学习来源于慕课网中的异步加载学习,来自徐宜生大神的灵感.本次也就是对大神所讲知识的一个总结及一些个人的感受吧. 这次是一个综合的Demo,主要里面涉及到的知识主要有:网络编程.异步加载.JSON解析.

浅谈android中的异步加载一

1.为什么需要异步加载. 因为我们都知道在Android中的是单线程模型,不允许其他的子线程来更新UI,只允许UI线程(主线程更新UI),否则会多个线程都去更新UI会造成UI的一个混乱有些耗时的操纵(例如网络请求等),如果直接放到主线程中去请求的话则会造成主线程阻塞,而我们系统有规定的响应时间,当响应的时间超过了了阻塞的时间就会造成"Application No Response",也就是我们熟知的ANR错误解决上述问题的时候:我们一般使用的是线程或者线程池+Handler机制如果线程

Android中android-async-http开源网络框架的简单使用

android-async-http开源网络框架是专门针对Android在Apache的基础上构建的异步且基于回调的http client.所有的请求全在UI线程之外发生,而callback发生在创建它的线程中,应用了Android的Handler发送消息机制. android-async-http的特点:(这段摘自网络) Make asynchronous HTTP requests, handle responses in anonymous callbacks 进行异步HTTP请求,处理响