Android-Query
在Google Code
上的网址:https://code.google.com/archive/p/android-query
Android-Query
在GitHub上的网址:https://github.com/chunjiangshieh/android-library-androidquery
Demo
地址:https://github.com/chunjiangshieh/android-demo-androidquery
在前端开发中,jQuery曾经是最流行的开发库,它极大地减少了执行异步任务和操作DOM
所需要的代码数量。Android-Query
想要为Android
开发者提供类似jQuery的功能。
Android-Query
使用起来非常简单,总共的类只有26
个,非常少。
AQuery
是核心类,几乎所有的操作都通过此类完成。
AQuery
的实现如下:
package com.androidquery;
import android.app.Activity;
import android.content.Context;
import android.view.View;
public class AQuery extends AbstractAQuery<AQuery> {
public AQuery(Activity act) {
super(act);
}
public AQuery(View view) {
super(view);
}
public AQuery(Context context) {
super(context);
}
public AQuery(Activity act, View root) {
super(act, root);
}
}
从AQuery
的实现,我们看到:AQuery
只提供了几个构造方法,其他所有的方法都是其父类AbstractAQuery
实现的。
需要注意的是:
在Activity
中使用AQuery
,可以调用public AQuery(Activity activity)
在Fragment
中使用AQuery
,可以调用public AQuery(Activity activity, View root)
如果通过LayoutInflater
解析了View
,可以调用public AQuery(View view)
AQuery
简化了附加事件处理程序的过程。它不会构建出接口或者匿名类,我们只需要确保它们不会把事件处理程序的方法名拼写错。示例:
aq.id(R.id.button).clicked(this, "buttonClicked");
AQuery
会根据条件来链接方法(conditionally chaining methods),让你可以回避所有检查。考虑一下这段代码:
aq.id(R.id.address).text(name).background(R.color.red).textColor(R.color.black).enabled(true).visible().clicked(this, "addressClicked");
如果控件地址不存在,那么后面所有设置方法和事件处理程序都会停止。尽管这可能会让调试更困难,但是它可以极大地减少了代码行数。
AQuery
还可以很容易地调用HTTP
请求。它包含了针对简单和多个部分POST
操作的支持, 并且能够接受二进制、JSON
、HTML
以及XML
格式的数据。
HTTP
请求支持所有的请求方式,比如GET
、POST FORM
、POST JSON
、PUT
、DELETE
等请求。
HTTP
协议的详细内容,请参看:HTTP
示例:
/**
* GET请求,是异步请求
* @param context 上下文
* @param urlPath URL的路径
* @param params URL的参数
* @param type 返回值类型
* @param callback 请求的回调
*/
public static <K> void asyncGet(Context context, String urlPath, List<BasicNameValuePair> params, Class<K> type, AjaxCallback<K> callback) {
AQuery aQuery = new AQuery(context);
String url = BASE_URL + urlPath;
String urlParams = "";
if (params != null && !params.isEmpty()) {
urlParams = URLEncodedUtils.format(params, "UTF-8");
}
if (!TextUtils.isEmpty(urlParams)) {
url += "?" + urlParams;
}
callback.url(url).type(type);
callback.header("Accept", "*/*");
callback.header("Connection", "Keep-Alive");
callback.header("Authorization", "xxxxx");
callback.header("User-Agent", "Android");
callback.header("Referer", "http://blog.fpliu.com");
aQuery.ajax(callback);
}
POST
用于提交数据,POST
一般必然包含请求体,而请求体可以有多种形式:FORM
、JSON
、XML
等格式化形式的字符串,或者其他自定义格式的数据形式。
示例一:
/**
* POST请求,请求体是表单,是异步请求
* @param context 上下文
* @param urlPath URL的路径
* @param params 请求参数
* @param type 返回值类型
* @param callback 请求的回调
*/
public static <K> void asyncPostForm(Context context, String urlPath, Map<String, Object> params, Class<K> type, AjaxCallback<K> callback) {
callback.header("Accept", "*/*");
callback.header("Connection", "Keep-Alive");
callback.header("Authorization", "xxxxx");
callback.header("User-Agent", "Android");
callback.header("Referer", "http://blog.fpliu.com");
AQuery aQuery = new AQuery(context);
aQuery.ajax(BASE_URL + urlPath, params, type, callback);
}
示例二:
/**
* POST请求,请求体是表单,是异步请求
* @param context 上下文
* @param urlPath URL的路径
* @param params 请求参数
* @param type 返回值类型
* @param callback 请求的回调
*/
public static <K> void asyncPostForm(Context context, String urlPath, List<BasicNameValuePair> params, Class<K> type, AjaxCallback<K> callback) {
try {
HttpEntity entity = new UrlEncodedFormEntity(params, HTTP.UTF_8);
callback.param(AQuery.POST_ENTITY, entity);
} catch (UnsupportedEncodingException e) {
DebugLog.e(TAG, "asyncPostForm()", e);
}
callback.url(BASE_URL + urlPath)
.header("Accept", "*/*")
.header("Connection", "Keep-Alive")
.header("Authorization", "xxxx")
.header("User-Agent", "Android")
.header("Referer", "http://blog.fpliu.com")
//其实默认就是表单提交,这个头可以不加
.header("Content-Type", "application/x-www-form-urlencoded")
.method(AQuery.METHOD_POST)
.type(type);
AQuery aQuery = new AQuery(context);
aQuery.ajax(callback);
}
示例:
/**
* POST请求,请求体是JSON,是异步请求
* @param context 上下文
* @param urlPath URL的路径
* @param json JSON字符串,使用String类型可以支持GSON、fastJson、json-lib等库的转化,而不局限于一种
* @param type 返回值类型
* @param callback 请求的回调
*/
public static <K> void asyncPostJson(Context context, String urlPath, String json, Class<K> type, AjaxCallback<K> callback) {
try {
StringEntity stringEntity = new StringEntity(json, HTTP.UTF_8);
stringEntity.setContentType("application/json");
callback.param(AQuery.POST_ENTITY, stringEntity);
} catch (UnsupportedEncodingException e) {
DebugLog.e(TAG, "asyncPostJson()", e);
}
callback.url(BASE_URL + urlPath)
.header("Accept", "*/*")
.header("Connection", "Keep-Alive")
.header("Authorization", "xxxx")
.header("User-Agent", "Android")
.header("Referer", "http://blog.fpliu.com")
//必须加这个头
.header("Content-Type", "application/json")
.method(AQuery.METHOD_POST)
.type(type);
AQuery aQuery = new AQuery(context);
aQuery.ajax(callback);
}
实际上,XML
提交只需要将JSON
提交的头中的Content-Type
修改为application/xml
即可。
示例:
/**
* POST请求,请求体是XML,是异步请求
* @param context 上下文
* @param urlPath URL的路径
* @param xml XML字符串
* @param type 返回值类型
* @param callback 请求的回调
*/
public static <K> void asyncPostXml(Context context, String urlPath, String xml, Class<K> type, AjaxCallback<K> callback) {
try {
StringEntity stringEntity = new StringEntity(xml, HTTP.UTF_8);
stringEntity.setContentType("application/xml");
callback.param(AQuery.POST_ENTITY, stringEntity);
} catch (UnsupportedEncodingException e) {
DebugLog.e(TAG, "asyncPostXml()", e);
}
callback.url(BASE_URL + urlPath)
.header("Accept", "*/*")
.header("Connection", "Keep-Alive")
.header("Authorization", "xxxx")
.header("User-Agent", "Android")
.header("Referer", "http://blog.fpliu.com")
//必须加这个头
.header("Content-Type", "application/xml")
.method(AQuery.METHOD_POST)
.type(type);
AQuery aQuery = new AQuery(context);
aQuery.ajax(callback);
}
示例:
/**
* POST请求,请求体是Multipart,是异步请求
* @param context 上下文
* @param urlPath URL的路径
* @param params 请求参数
* @param type 返回值类型
* @param callback 请求的回调
*/
public static <K> void asyncPostMultipart(Context context, String urlPath, Map<String, Object> params, Class<K> type, AjaxCallback<K> callback) {
callback.header("Accept", "*/*");
callback.header("Connection", "Keep-Alive");
callback.header("Authorization", "xxxx");
callback.header("User-Agent", "Android");
callback.header("Referer", "http://blog.fpliu.com");
AQuery aQuery = new AQuery(context);
aQuery.ajax(BASE_URL + urlPath, params, type, callback);
}
AQuery
会根据Map
中的Value
的类型不同, 自动以Multipart
方式进行发送POST
请求。
PUT
请求与POST
请求在协议本身,除了请求方法本身的不同,其他方面没有任何差别。 从Restful
风格上讲:只是语义上不同,POST
用于创建资源,而PUT
用于更新资源。
所以将
.method(AQuery.METHOD_POST)
修改为:
.method(AQuery.METHOD_PUT)
即可。
Delete
请求用于删除资源,不应该携带大量信息,所以,一般Delete
请求没有实体。
由于请求的数据有可能是一个文件(File
)、一张图片(Bitmap
)、字符串、XML
、JSON
等。 而XML
和JSON
又涉及到解析的问题。JSON
解析可以使用Google-Gson
、fastjson
等。
请求的时候,要求一个参数Class<K> type
,它是返回的数据的类型,默认的,Android-Query
只支持下面这些类型:
如果想要支持任意类型,必须实现com.androidquery.callback.Transformer
接口,下面是一个实现参考:
public final class MyTransformer implements Transformer {
private static final String TAG = MyTransformer.class.getSimpleName();
@Override
public <T> T transform(String url, Class<T> type, String encoding, byte[] data, AjaxStatus status) {
Gson gson = new Gson();
try {
String jsonResult = new String(data);
DebugLog.d(TAG, "result = " + jsonResult);
return gson.fromJson(jsonResult, type);
} catch (Exception e) {
DebugLog.e(TAG, "transform()", e);
return newInstance(type);
}
}
private static <R> R newInstance(Class<R> clazz) {
try {
Constructor<R> constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
return (R) constructor.newInstance();
} catch (Exception e) {
DebugLog.e(TAG, "newInstance()", e);
return null;
}
}
}
然后设置Transformer
,如下:
callback.transformer(new MyTransformer());
大部分时候,我们需要的是异步调用,但有些时候,我们也需要同步调用。
示例:
String url = "http://www.google.com/uds/GnewsSearch?q=Obama&v=1.0";
AjaxCallback<JSONObject> callback = new AjaxCallback<JSONObject>();
callback.url(url).type(JSONObject.class);
AQuery aQuery = new AQuery(context);
aQuery.sync(callback);
JSONObject result = callback.getResult();
AjaxStatus status = callback.getStatus();
下载文件有单独的接口,在AQuery
中有下面三个重载的接口:
public T download(String url, File target, AjaxCallback<File> cb)
public T download(String url, File target, Object handler, String callback)
public T download(String url, File target, boolean resume, AjaxCallback<File> cb)
public T download(String url, File target, boolean resume, Object handler, String callback)
调用这几个函数进行下载。resume
参数表示是否要进行断点续传。
示例:
/**
* 下载文件
*
* @param context 上下文
* @param url 请求资源的路径
* @param desFile 存储位置
* @param callback 请求的回调
*/
public static void asyncDownload(Context context, String url, File desFile, AjaxCallback<File> callback) {
callback.header("Accept", "*/*");
callback.header("Connection", "Keep-Alive");
callback.header("Authorization", "xxxxxxx");
callback.header("User-Agent", "Android");
callback.header("Referer", "http://blog.fpliu.com");
AQuery aQuery = new AQuery(context);
aQuery.download(url, desFile, true, callback);
}
Android-Query
支持异步加载图片,我们使用一行代码就能下载图片,对其进行缓存,并把它载入到控件中。
AQuery
提供了下面这些重载的图片加载的函数:
public T image(int resid)
public T image(Drawable drawable)
public T image(Bitmap bm)
public T image(String url)
public T image(String url, boolean memCache, boolean fileCache)
public T image(String url, boolean memCache, boolean fileCache, int targetWidth, int fallbackId)
public T image(String url, boolean memCache, boolean fileCache, int targetWidth, int fallbackId, Bitmap preset, int animId)
public T image(String url, boolean memCache, boolean fileCache, int targetWidth, int fallbackId, Bitmap preset, int animId, float ratio)
public T image(String url, ImageOptions options)
public T image(BitmapAjaxCallback callback)
public T image(String url, boolean memCache, boolean fileCache, int targetWidth, int resId, BitmapAjaxCallback callback)
public T image(File file, int targetWidth)
public T image(File file, boolean memCache, int targetWidth, BitmapAjaxCallback callback)
public T image(Bitmap bm, float ratio)