Android程序中REST Clients是一个很常见的使用场景,不过一些书籍介绍的都是很入门的网络访问,离在程序实际使用的场景还差的很远,今天我大概介绍一下自己的实践经验
网络访问
要作REST Client网络访问时第一步,一般认为2.3之前用Apache HttpClient,2.3之后使用HttpURLConnection具体原因参见这里,因为无论是HttpClient和HttpURLConnection书中都有介绍,此处就不展开了。
不过实际使用中HttpURLConnection还是很繁琐的,我一般在需要网络请求的地方会采用OkHttp,此处引用一下OkHttp官网的一段GET请求代码大家看看
OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
异步请求
虽然有了网络请求的代码,但是在Android中是不允许在ui线程进行网络请求的,官方的解决方法有两个
1. 新建一个Work Thread进行网络请求,请求结束之后使用Handler再切换到UI线程继续结果处理。具体实现参见这里
2. 使用AsyncTask
AsyncTask写起来很简单,一般大家都会采用AsyncTask。两个方案也都有无数实现示例,此处聊一些需要注意的点
1. AsyncTask其实可以看做Work Thread+Handler的封装
2. AsyncTask一个示例只能执行一次,所以如果有重复后台任务-》前台任务这种切换场景的话Work Thread+Handler是更好的选择。
3. AsyncTask本身存在一些缺陷,另外各版本AsyncTask实现也有些差异使用时需要注意AsyncTask中的线程池的策略是否满足你当前的情景
4. 一般使用Handler的时候会用匿名类实现,使用AsyncTask的时候会使用内部类。这两个常见的场景都容易造成内存泄漏,使用时需注意。
5. AsyncTask或者Work Thread + Handler的方案实际使用中需考虑Activity LifeCycle变化,这块内容后续会详细讨论
序列化
RESTFul接口一般会返回json结果,使用HttpURLConnection读到的是json 字符串。我们一般使用的是数据对象,此时我们要将读到的字符串序列化为合适的对象。最常见的解决方案就是Google的Gson,此处引用部分文档代码大家看一下
class BagOfPrimitives {
private int value1 = 1;
private String value2 = "abc";
private transient int value3 = 3;
BagOfPrimitives() {
// no-args constructor
}
}
(Serialization)
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj);
==> json is {"value1":1,"value2":"abc"}
Note that you can not serialize objects with circular references since that will result in infinite recursion.
(Deserialization)
BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
==> obj2 is just like obj
总结
至此异步网络请求并序列化为对象的官方方案都讨论完了,但是在实践中大家都不这么干……所以你也没看到实际的示例代码,下一篇咱们讨论一下在实践中大家的实现方案。