Android框架学习笔记02AndroidAsycHttp框架

上一篇中我们介绍了OkHttp3.0框架的基本使用方法,这一篇我们学习一下Android的另外一个网络请求框架——AsyncHttpClient框架。Asynchttpclient框架是一个开源的异步网络请求框架,所有的网络都在Android的非UI线程中,通过回调方法处理请求结果,无论是向网络请求数据还是上传数据都非常方便,而且这个框架非常体积非常小,只有90K左右的大小,我们可以轻松使用它,下面我们介绍一下这个框架:

概述

Asynchttpclient框架有如下的特征:

  • 处理异步Http请求,并通过匿名内部类处理回调结果

  • Http异步请求均位于非UI线程,不会阻塞UI操作

  • 通过线程池处理并发请求处理文件上传、下载,响应结果自动打包JSON格式

  • 自动处理连接断开时请求重连

  • 永久的cookie保存,内部实现用的是Android的SharedPreferences

  • 通过BaseJsonHttpResponseHandler和各种json库集成

  • 支持SAX解析器

  • 支持各种语言和content编码,不仅仅是UTF-8

  • 自动的gzip响应解码

  • 内置多种形式的响应解析,有原生的字节流,string,json对象,甚至可以将response写到文件中

这里只是简单的介绍一下,具体需要实现细节需要我们在开发中实际去体会。

我们来学习一下Asynchttpclient里面的具体的类:

  • AsyncHttpRequest类:继承自Runnabler,被submit至线程池执行网络请求并发送start,success等消息

  • AsyncHttpResponseHandler类:接收请求结果,一般重写onSuccess及onFailure接收请求成功或失败的消息,还有onStart,onFinish等消息

  • TextHttpResponseHandler类:继承自AsyncHttpResponseHandler,只是重写了AsyncHttpResponseHandler的onSuccess和onFailure方法,将请求结果由byte数组转换为String

  • JsonHttpResponseHandler类:继承自TextHttpResponseHandler,同样是重写onSuccess和onFailure方法,将请求结果由String转换为JSONObject或JSONArray

  • BaseJsonHttpResponseHandler类:继承自TextHttpResponseHandler,是一个泛型类,提供了parseResponse方法,子类需要提供实现,将请求结果解析成需要的类型,子类可以灵活地使用解析方法,可以直接原始解析,使用gson等

  • RequestParams类:请求参数,可以添加普通的字符串参数,并可添加File,InputStream上传文件

  • AsyncHttpClient类:核心类,使用HttpClient执行网络请求,提供了get,put,post,delete,head等请求方法,使用起来很简单,只需以url及RequestParams调用相应的方法即可,还可以选择性地传入Context,用于取消Content相关的请求,同时必须提供ResponseHandlerInterface(AsyncHttpResponseHandler继承自ResponseHandlerInterface)的实现类,一般为AsyncHttpResponseHandler的子类,AsyncHttpClient内部有一个线程池,当使用AsyncHttpClient执行网络请求时,最终都会调用sendRequest方法,在这个方法内部将请求参数封装成AsyncHttpRequest(继承自Runnable)交由内部的线程池执行

  • SyncHttpClient类:继承自AsyncHttpClient,同步执行网络请求,AsyncHttpClient把请求封装成AsyncHttpRequest后提交至线程池,SyncHttpClient把请求封装成AsyncHttpRequest后直接调用它的run方法

这里就不介绍里面的方法了,具体的可以去Github看一下源码:https://github.com/loopj/android-async-http

或者可以看一下API:https://loopj.com/android-async-http/doc/

再简单介绍一下Asynchttpclient框架的请求流程:

  1. 首先调用AsyncHttpClient的get或post等方法发起网络请求

  2. 所有的请求都走了sendRequest,在sendRequest中把请求封装为了AsyncHttpRequest,并添加到线程池执行

  3. 当请求被执行时(即AsyncHttpRequest的run方法),执行AsyncHttpRequest的makeRequestWithRetries方法执行实际的请求,当请求失败时可以重试。并在请求开始,结束,成功或失败时向请求时传的ResponseHandlerInterface实例发送消息

  4. 基本上使用的都是AsyncHttpResponseHandler的子类,调用其onStart,onSuccess等方法返回请求结果

关于Asynchttpclient就简单介绍到这里,下面介绍一下Asynchttpclient的具体使用

使用

Asynchttpclient框架的使用步骤基本是:

  1. 创建一个AsyncHttpClient对象

  2. 通过RequestParams对象设置请求参数,这个是可选择的

  3. 调用AsyncHttpClient对象里面的方法,实现请求或者上传数据。这里需要实现内部类回调,框架自己有实现有,不需要我们自己手动实现,我们只需要调用即可。

如果是在Android Studio中使用,需要在gradle中添加:

compile 'com.loopj.android:android-async-http:1.4.9'

如果是Eclipse的话需要去GitHub或者官网下载相应版本的JAR吧,GitHub地址在上文中有给出,下面是Asynchttpclient的官网:http://loopj.com/android-async-http/

下面看一下具体的代码:

AsyncHttpClient client = new AsyncHttpClient();
client.get("https://www.google.com", new AsyncHttpResponseHandler() {

       @Override
       public void onStart() {
        // called before request is started
    }

    @Override
    public void onSuccess(int statusCode, Header[] headers, byte[] response) {
        // called when response HTTP status is "200 OK"
    }

    @Override
    public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
        // called when response HTTP status is "4XX" (eg. 401, 403, 404)
    }

    @Override
    public void onRetry(int retryNo) {
            // called when request is retried
    }
    });

这里是Get请求的写法,官方推荐我们使用静态的写法:

import com.loopj.android.http.*;

public class TwitterRestClient {
  private static final String BASE_URL = "https://api.twitter.com/1/";

  private static AsyncHttpClient client = new AsyncHttpClient();

  public static void get(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
      client.get(getAbsoluteUrl(url), params, responseHandler);
  }

  public static void post(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
      client.post(getAbsoluteUrl(url), params, responseHandler);
  }

  private static String getAbsoluteUrl(String relativeUrl) {
      return BASE_URL + relativeUrl;
  }
}

这样方便我们使用。

下面我们使用这个框架实现GET请求、POST请求、文件上传、文件下载这四个功能,这里没有实现保存Cookie的功能,有需要的可以扩展实现:

实现GET请求

我们先看一下具体实现的代码:

AsyncHttpUtils.get(UrlUtils.REQUEST_URL + UrlUtils.URL_KEY, null, new JsonHttpResponseHandler() {
        @Override
        public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
            super.onSuccess(statusCode, headers, response);
            Log.i(TAG, getResources().getString(R.string.req_success));
            Log.i(TAG, "======================================================================");
            Log.i(TAG, response.toString());
            Log.i(TAG, "======================================================================");
        }

        @Override
        public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONArray errorResponse) {
            super.onFailure(statusCode, headers, throwable, errorResponse);
            Log.i(TAG, getResources().getString(R.string.req_failed));
        }
    });

这样就可以实现一个GET请求,请求是在非UI线程中,有请求成功的回调和请求失败的回调,我们更新UI需要通过发消息或者其它方式实现,不能再请求成功的回调方法里面直接更新UI。其中RequestParams是可以选择的,没有请求参数可以直接设置为null。非常简单,就不在做过多的介绍了。

实现POST请求

我们还是先看一下具体的代码:

 RequestParams requestParams = new RequestParams();
    requestParams.put("username", "Devin");
    requestParams.put("password", "Devin");
    AsyncHttpUtils.post(UrlUtils.POST_URL, requestParams, new AsyncHttpResponseHandler() {
        @Override
        public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
            Log.i(TAG, getResources().getString(R.string.req_success));
        }

        @Override
        public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
            Log.i(TAG, getResources().getString(R.string.req_failed));
        }
    });

POST请求需要上传一些参数,框架提供了设置参数的类RequestParams,其中,RequestParams类似于Map,是键值对的形式,添加请求参数有三种方式:

第一种就是像我上面代码一样,创建一个空的RequestParams对象,然后通过put方法将参数写入;

第二种则是创建的时候就直接添加,例如:

RequestParams params = new RequestParams("single", "value");

第三种是将参数写入一个Map中,然后将Map赋给RequestParams,例如:

HashMap<String, String> paramMap = new HashMap<String, String>();
paramMap.put("key", "value");
RequestParams params = new RequestParams(paramMap);

这三种方式无论哪一种都可以实现封装请求参数。

实现文件上传

使用Asynchttpclient实现文件上传也非常简单,我们先看一下代码:

 RequestParams requestParams = new RequestParams();
    File file = new File("/sdcard/okhttp-3.4.1.jar");
    try {
        requestParams.put("file", file);
        AsyncHttpUtils.post(UrlUtils.UPLOAD_URL, requestParams, new AsyncHttpResponseHandler() {
            @Override
            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                Log.i(TAG, getResources().getString(R.string.req_success));
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
                Log.i(TAG, getResources().getString(R.string.req_failed));
            }
        });
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

可以看到,这里文件上传是将文件封装到RequestParams中的,Asynchttpclient框架提供的封装文件到RequestParams中有三种方法,分别是:

第一种是将文件转成流的形式封装到RequestParams中,例如:

InputStream myInputStream = blah;
RequestParams params = new RequestParams();
params.put("secret_passwords", myInputStream, "passwords.txt");

第二种就是像上面的代码一样,将文件直接封装到RequestParams中

第三种是将文件转成二进制数组的形式,例如:

byte[] myByteArray = blah;
RequestParams params = new RequestParams();
params.put("soundtrack", new ByteArrayInputStream(myByteArray), "she-wolf.mp3");

这三种方法无论哪一种都可以实现封装文件到RequestParams中,然后调用AsyncHttpClient对象中的方法实现上传,具体使用哪一种看个人喜欢了。

实现文件下载

使用Asynchttpclient框架实现文件下载也非常简单,我们先看一下代码:

 AsyncHttpUtils.download(UrlUtils.DOWNLOAD_URL, null, new FileAsyncHttpResponseHandler(getActivity()) {
        @Override
        public void onFailure(int statusCode, Header[] headers, Throwable throwable, File file) {
            Log.i(TAG, getResources().getString(R.string.req_failed));
        }

        @Override
        public void onSuccess(int statusCode, Header[] headers, File file) {
            Log.i(TAG, getResources().getString(R.string.req_success));
        }
    });

实现文件下载,回调选择的就是FileAsyncHttpResponseHandler这个Asynchttpclient框架提供的类,这可以非常方便的实现文件的下载。

关于Asynchttpclient框架就简单介绍到这里了,还有保存Cookie这个功能没有实现,不过实现也非常简单,不懂得可以看一下官方的文档,官网地址上文中有给出了。

文中Demo已经上传到GitHub中,有兴趣的可以去了解一下:https://github.com/Devin1102/AndroidFrameDemo

最后,欢迎留言交流学习!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,997评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,603评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,359评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,309评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,346评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,258评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,122评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,970评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,403评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,596评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,769评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,464评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,075评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,705评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,848评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,831评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,678评论 2 354

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,093评论 25 707
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,243评论 11 349
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,625评论 18 399
  • 独立,我最近一直在想的问题。觉得有点懂的,经济的独立只是表层的东西,其实最重要的是心理上和精神上,所谓自己的内心拥...
    WoodSage阅读 234评论 0 0
  • 把美好的祝福送给亲爱的家人们一天好心情,每天更深的了解功课,更多的活在功课中!理解功课没有重点,活出功课没有尽头!...
    人间讲堂阅读 357评论 0 0