作为一个Android开发的大龄初学者,面对扑面而来的各种姿势的Android的开源组件,让人倍感窒息,难以应对。无奈为了养家糊口,虽然已近不惑,人老珠黄,也只能废寝忘食,逐个体位细细揣摩研究,不断以身实践,争取早日小成。
话说那是一个阳光明媚的下午,我坐在街口转角处优雅的网络会所里,品着一杯上好的Coca-Cola,研读着oschina客户端源码,身旁不时传来:“一起上搞死他,他没蓝了...!”。
从火蚁(oschina客户端的开发者之一,向他们致敬)那里知道了async-http-client开源库,为了千千万万个没过英语四级的程序猿GG,就在这里翻译个作者写的"用户说明书"先...
async-http-client库是一个基于回调函数的Http异步通信客户端Android组件,是在Apache的HttpClient库的基础上开发构建而成的。这里的异步,是指它所有的网络请求都是在app的UI线程之外的独立工作线程中执行。而开发者通过利用Android的消息处理机制,把我们所需要编写的回调函数放在这个回调函数的创建线程中执行(一般就是UI线程),所以使用起来非常方便,有了它,Boss再也不用担心我被多线程同步搞死了。除了能应用在开发普通App上,还可以用来开发Service或后台线程,async-http-client库可以自已分辨是被用在哪一种应用下,不需要额外的设置。
异步方式发起Http请求,可以使用匿名回调函数处理网络应答;
在UI主线程之外的工作线程发起Http请求;
通过使用线程池解决了资源并发的效率问题;
通过使用RequestParams类,可完成GET/POST的参数构建;
支持文件的分段下载功能;
支持上传JSON数据流;
对重定向循环、重定向相对路径异常进行了处理
代码体积小,全部功能只占90kb;
专门针对移动网络的不稳定性,对请求重发进行了优化,实现了自动智能处理;
传输时支持数据压缩,可自动对应答进行gzip解压处理;
使用BinaryHttpResponseHandler,可进行较底层的tcp/ip协议数据通信;
JsonHttpResponseHandler内嵌JSON语法分析功能,可完成JSON数据解析;
FileAsyncHttpResponseHandler可直接将应答保存到本地文件中;
支持cookie的持久化,可使用App的SharedPreferences保存cookie信息;
通过BaseJsonHttpResponseHandler可与Jackson JSON, Gson等第三方JSON框架库集成;
SaxAsyncHttpResponseHandler支持SAX语法分析
除了UTF-8,还支持其它语言编码。
Instagram
Frontline Commando (Glu Games)
Heyzap
Pose
(以上应用我一个都没用过,反正说明async-http-client很diao就对了)
1. 在Gradle build脚本中增加
dependencies {
compile 'com.loopj.android:android-async-http:1.4.8'
}
2. 引入http包
import com.loopj.android.http.*;
3. 创建AsyncHttpClient 实例,并发出请求
AsyncHttpClientclient = new AsyncHttpClient();
client.get("http://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, Throwablee){
// called when response HTTP status is "4XX" (eg. 401, 403, 404)
}
@Override
public void onRetry(int retryNo){
// called when request is retried
}
});
创建AsyncHttpClient的静态实例进行通信更加方便,以使用Twitter提供的Api为例(此处使用Twitter作例子,站在大墙里面的我们看看就行了):
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;
}
}
TwitterRestClient 类中创建了一个AsyncHttpClient的静态实例,通过静态实例与Twitter进行数据通信,共有两个对外的接口函数get,set,也都是静态的。下面是如何在代码中使用这个类:
import org.json.*;
import com.loopj.android.http.*;
class TwitterRestClientUsage {
public void getPublicTimeline() throws JSONException {
TwitterRestClient.get("statuses/public_timeline.json", null,
new JsonHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers,
JSONObject response) {
// If the response is JSONObject instead of expected JSONArray
}
@Override
public void onSuccess(int statusCode, Header[] headers,
JSONArray timeline) {
// Pull out the first event on the public timeline
JSONObject firstEvent = timeline.get(0);
String tweetText = firstEvent.getString("text");
// Do something with the response
System.out.println(tweetText);
}
});
}
}
这里使用了匿名回调函数,并且是JsonHttpResponseHandler类型,它内嵌了Json语言解析器,可直接在处理函数中使用对应答数据解析后的Json数据,真是即方便又快捷。
async-http-client库包含一个PersistentCookieStore类,这个类实现了CookieStore接口(源自Apache HttpClient包),可自动将cookie信息保存到应用的SharedPreferences储存中。
如果你的应用需要使用cookie维护用户授权session,这是非常有用,方便的。即使关闭了app或重新启动app,应用也可以保持用户已登录的状态。
首先创建一个AsyncHttpClient实例:
AsyncHttpClient myClient = new AsyncHttpClient();
为这个实例设置一个新建的PersistentCookieStore的实例以进行cookie存储,调用这个PersistentCookieStore实例的构造函数时,使用一个activity或application context作参数(一般用this就可以了):
PersistentCookieStore myCookieStore = new PersistentCookieStore(this);
myClient.setCookieStore(myCookieStore);
这样由服务端接收到的cookie将会自动存储在你的android设备上。如果要添加自己的cookie,只需要构建一个新的cookie并调用addCookie函数:
BasicClientCookie newCookie = new BasicClientCookie("cookiesare", "awesome");
newCookie.setVersion(1);
newCookie.setDomain("mydomain.com");
newCookie.setPath("/");
myCookieStore.addCookie(newCookie);
大部分应用的url请求都需要带各种参数,在Get/Post请求时增加参数,可使用RequestParams类。
可以使用以下三种方法构建RequestParams实例:
1. 创建一个空的RequestParams实例,并增加参数:
RequestParams params = new RequestParams();
params.put("key", "value");
params.put("more", "data");
2. 只有一个参数,创建RequestParams实例:
RequestParams params = new RequestParams("single", "value");
3. 利用已存在的Map键值对创建RequestParams实例:
HashMap<String, String> paramMap = new HashMap<String, String>();
paramMap.put("key", "value");
RequestParams params = new RequestParams(paramMap);
RequestParams类还可以用来实现文件分段上传,有以下三种实现方式:
1. 将InputStream作为参数加入RequestParams:
InputStream myInputStream = blah;
RequestParams params = new RequestParams();
params.put("secret_passwords", myInputStream, "passwords.txt");
2. 直接将File对象增加到RequestParams中:
File myFile = new File("/path/to/file.png");
RequestParams params = new RequestParams();
try {
params.put("profile_picture", myFile);
} catch(FileNotFoundException e) {}
3. 使用二进制字节数组:
byte[] myByteArray = blah;
RequestParams params = new RequestParams();
params.put("soundtrack", new ByteArrayInputStream(myByteArray), "she-wolf.mp3");
FileAsyncHttpResponseHandler用来获取二进制数据,比如图像、声音等文件。
AsyncHttpClient client = new AsyncHttpClient();
client.get("https://example.com/file.png",
new FileAsyncHttpResponseHandler(/* Context */ this) {
@Override
public void onSuccess(int statusCode, Header[] headers, File response) {
// Do something with the file `response`
}
});
在实际应用环境中,某些服务器资源需要用户名/密码授权认证才能访问,这类资源访问需要使用HTTP Basic Access Authentication协议,请求才能被处理。可以使用setBasicAuth函数提供认证信息。
为主机或域名访问设置用户名/密码,默认状态认证信息对所有主机、端口或域名有效。
AsyncHttpClient client = new AsyncHttpClient();
client.setBasicAuth("username","password/token");
client.get("https://example.com");
更为推荐的方式是对特定的主机或端口提供授权认证信息:
AsyncHttpClient client = new AsyncHttpClient();
client.setBasicAuth("username","password",
new AuthScope("example.com", 80, AuthScope.ANY_REALM));
client.get("https://example.com");