近段时间使用了一些 Android 平台的第三方库,发现用起来很爽,可以大大提升开发效率,特此记录下。
主要使用了以下几个库:
Butterknife 是一个 View 的依赖注入框架,目的是实现 View 查找、事件监听绑定,可以减少代码量,让代码看起来更清晰。Retrofit 是一个网络请求框架,封装了访问网络方面的细节,可以让开发者更加专注于业务方面。Fresco 则是一个图片加载框架,用于加载不同类型的图片,包括本地、网络等来源的,提供了图片处理方面的解决方案。Logger 则是关于 Log 方面的,是对 Android 自带 log 的增强,更加方便易用。Gson 是用来 json 格式数据的,可以和 Retrofit 搭配来用,直接将服务端返回的 json 数据转换为 Java 对象。
为了熟悉这些库的使用,写了个练手的小应用,通过豆瓣开放平台的 API,实现豆瓣读书的搜索功能,主要的需求为向豆瓣的服务器发起图书搜索请求,然后将返回的数据解析显示,很简单的一个需求,其中涉及到了网络和图片加载两大方面的内容。这个需求是参考了网上一位叫阳春面博主的,在这里表示感谢,他的博客写的很好,可以去看看。应用效果如下:

Butterknife
简介
相信从事 Android 应用开发的同学都写过不少的 findViewById() 代码,界面复杂点的就会有一堆 findViewById() 出现,与之类似的还有 setOnClickListener() 等,Butterknife 就是为了减少这些重复而没有太多意义的代码的,使代码更简洁,举个栗子对比下。
使用前:
1 | protected Toolbar mToolbar; |
使用后:
1 | (R.id.toolbar) |
直接在定义的时候就绑定了,貌似代码行数并没有少啊,反而还多了一些,但是不觉得看起来更清晰么?
其实 Butterknife 还可以绑定一些常用的事件,比如 onClick()、onItemClick()、OnCheckedChanged()等,举个栗子:
1 | ({R.id.toolbar, R.id.drawer_layout, R.id.search_view}) |
@OnClick 注解作用就等同于 setOnClickListener(),还有其他的注解,作用类似,更多用法可以参考 Butterknife官方文档。有一个需要注意的地方是变量或类不能是 private 修饰的。
集成到项目
添加 Butterknife 到项目需要两个步骤:
在项目级别的
build.grade添加如下内容:1
2
3
4
5
6
7
8buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}在应用级别的
build.gradle添加如下内容:1
2
3
4
5
6
7
8
9
10apply plugin: 'android-apt'
android {
...
}
dependencies {
compile 'com.jakewharton:butterknife:8.4.0'
apt 'com.jakewharton:butterknife-compiler:8.4.0'
}
Retrofit
简介
在开发 Android 网络方面的时候,直接使用原生的 API 个人感觉是比较痛苦的,需要涉及的东西比较多,各方面都需要考虑周到,Retrofit 则可以解决这些痛苦,原来网络编程也可以这么爽。Retrofit 是在 OkHttp 上进一步的封装,还可以将返回结果直接解析转换出来,支持常见的 json、xml 等数据格式,比如服务器返回的是 json 数据,跟 Gson 搭配使用简直不能更方便了。
使用套路
比如下面这样的 json 数据,是搜索豆瓣读书返回的结果:
1 | https://api.douban.com/v2/book/search?q=穆斯林的葬礼 |

大概有以下这么几个步骤将上面的数据解析成 Java 对象:
新建一个类,里面的字段跟搜索结果对应
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65/**
* 豆瓣图书搜索结果的响应
* @author cengt 2016/10/22 12:44
* @version v1.0
*/
public class QueryDBBookRespone {
/** 请求的搜索结果数量 */
("count")
private int mCount;
/** 搜索结果起始位置 */
("start")
private int mStart;
/** 返回的搜索结果数量 */
("total")
private int mTotal;
/** 搜索的图书列表 */
("books")
private List<DBBook> mBooks;
public int getCount() {
return mCount;
}
public void setCount(int count) {
mCount = count;
}
public int getStart() {
return mStart;
}
public void setStart(int start) {
mStart = start;
}
public int getTotal() {
return mTotal;
}
public void setTotal(int total) {
mTotal = total;
}
public List<DBBook> getBooks() {
return mBooks;
}
public void setBooks(List<DBBook> books) {
mBooks = books;
}
public String toString() {
return "QueryDBBookRespone{" +
"mCount=" + mCount +
", mStart=" + mStart +
", mTotal=" + mTotal +
", mBooks=" + mBooks +
'}';
}
}@SerializedName()注解是 Gson 这个库的,表明序列化的时候字段使用的名称,这个名称需要跟 json 数据里面的 key 对应。接下来定义一个
interface1
2
3
4
5
6
7
8
9
10
11
12
13
14/**
* 豆瓣读书API
* @author cengt 2016/10/22 11:20
* @version v1.0
*/
public interface DBBookService {
/**
* 通过关键字搜索图书
* @param keyword 想要搜索的关键字
*/
("book/search")
Call<QueryDBBookRespone> searchBooksByKeyword(@Query("q") String keyword);
}@GET()表明这个请求是 Get 方式的,类似的还是@POST()、@PUT()、@DELETE()等,里面的值为 URL 的路径,这个路径是相对的,相对于 BaseURL 的,等下就会看到了。@Query()指明 URl 里面的参数 。如果这里不明白的建议看看这两篇博客: 你应该知道的HTTP基础知识,你真的会用Retrofit2吗?Retrofit2完全教程,感谢博主。最后就是发起请求了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24/**
** 搜索图书(默认搜索20条记录)
* @param query 搜索的关键字
*/
public void search(String query) {
Logger.d("query = " + query);
Retrofit retrofit = RetrofitManager.getIntance().createDBBookRetrofit();
DBBookService bookService = retrofit.create(DBBookService.class);
bookService.searchBooksByKeyword(query).enqueue(new Callback<QueryDBBookRespone>() {
public void onResponse(Call<QueryDBBookRespone> call, Response<QueryDBBookRespone> response) {
Logger.d("query book done");
onSearchRespone(response);
}
public void onFailure(Call<QueryDBBookRespone> call, Throwable t) {
String msg = t.getLocalizedMessage();
Logger.e(t, "query book error " + msg);
onSearchFailure(msg);
}
});
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public class RetrofitManager {
...
/** 豆瓣读书API的基础路径 */
public static final String BASE_URL_DOUBAN_BOOK = "https://api.douban.com/v2/";
public Retrofit createRetrofit(String baseUrl) {
if (baseUrl == null) {
return null;
}
return new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
...
}新建
Retrofit对象时需要传入一个baseUrl参数,这个参数跟上面的路径组成完整的 URl,addConverterFactory()表示使用 Gson 解析返回来的数据,最后通过response对象就可以直接拿到转换好的 Java 对象了。1
List<DBBook> books = respone.body().getBooks();
使用 Retrofit 基本上只需要关心业务方面的东西了,其中的实现细节根本不用再理会,大大简化了网络方面的开发。
集成到项目
添加下面内容到应用级别的 build.gradle:
1 | compile 'com.squareup.retrofit2:retrofit:2.1.0' |
更多的使用方面参考 Retrofit官方文档,国内也有很多这方面的优秀博客。
Gson
Gson 用来解析 json 数据的,这里主要跟 Retrofit 配合使用,就不过多介绍了。你真的会用Gson吗?Gson使用指南 这里有写的很好的博客,再次感谢博主。
Fresco
Fresco 是一个图片加载库,有了 Fresco,妈妈再也不用担心图片过大出现 OOM 了,也不需要自己管理缓存方面的问题了,不管是本地还是网络的图片,一切都是那么的方便,生活是如此的美好。Fresco 缺点方面就是体积比较大,会让应用的大小增加,如果在意应用大小的,可以考虑其他的图片加载库,比如: Glide。Fresco 用法方面比较简单,使用 SimpleDraweeView 代替 ImageView 就差不多了,大部分需求应该都可以满足了。关于 Fresco 有一点是要特别要提一下的,这货有官方的中文版文档!!!太有良心了!英语没过四级的同学不用瑟瑟发抖了,而且 Fresco官方文档 也写的很好。这里简单记录下用法。
基本用法
初始化
Fresco,只需一次即可,在Application做这件事再适合不过了。1
2
3
4
5
6
7public class MyApplication extends Application {
public void onCreate() {
super.onCreate();
Fresco.initialize(this);
}
}添加
SimpleDraweeView1
2
3
4
5<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/db_book_detail_cover"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>需要注意的是
SimpleDraweeView不支持wrap_content,必须指定大小或使用match_parent加载图片
1
draweeView.setImageURI(imgUrl);
集成到项目
在应用级别下的build.gradle加入如下内容:1
compile 'com.facebook.fresco:fresco:0.12.0'
更多的用法参考 Fresco官方文档。
推荐博文
Logger
简介
Logger 是一个 Log 库,功能比 Android 自带的 Log 要强大,用过之后再也不想用回原来的 Log 了,支持输出线程、类、函数等信息,漂亮的 json 数据格式,直接跳转到源码行数等功能,使用方法和 Log 类似,更多详情见 Logger。附上几张官方的图片:

集成到项目
在应用级别下的 build.gradle 加入如下内容:
1 | compile 'com.orhanobut:logger:1.15' |
源码
源码在这里,欢迎 start 或 fork。