Android部分第三方库使用总结

近段时间使用了一些 Android 平台的第三方库,发现用起来很爽,可以大大提升开发效率,特此记录下。
主要使用了以下几个库:

Butterknife 是一个 View 的依赖注入框架,目的是实现 View 查找、事件监听绑定,可以减少代码量,让代码看起来更清晰。Retrofit 是一个网络请求框架,封装了访问网络方面的细节,可以让开发者更加专注于业务方面。Fresco 则是一个图片加载框架,用于加载不同类型的图片,包括本地、网络等来源的,提供了图片处理方面的解决方案。Logger 则是关于 Log 方面的,是对 Android 自带 log 的增强,更加方便易用。Gson 是用来 json 格式数据的,可以和 Retrofit 搭配来用,直接将服务端返回的 json 数据转换为 Java 对象。

为了熟悉这些库的使用,写了个练手的小应用,通过豆瓣开放平台的 API,实现豆瓣读书的搜索功能,主要的需求为向豆瓣的服务器发起图书搜索请求,然后将返回的数据解析显示,很简单的一个需求,其中涉及到了网络和图片加载两大方面的内容。这个需求是参考了网上一位叫阳春面博主的,在这里表示感谢,他的博客写的很好,可以去看看。应用效果如下:

Butterknife

简介

相信从事 Android 应用开发的同学都写过不少的 findViewById() 代码,界面复杂点的就会有一堆 findViewById() 出现,与之类似的还有 setOnClickListener() 等,Butterknife 就是为了减少这些重复而没有太多意义的代码的,使代码更简洁,举个栗子对比下。
使用前:

1
2
3
4
5
6
7
8
9
10
protected Toolbar mToolbar;
protected DrawerLayout mDrawer;
protected MainNavigationView mNavigationView;

private void initView() {
mToolbar = (Toolbar) findViewById(R.id.toolbar);
mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
mNavigationView = (MainNavigationView) findViewById(R.id.nav_view);
mSearchView = (DBBookSearchView) findViewById(R.id.search_view);
}

使用后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@BindView(R.id.toolbar)
protected Toolbar mToolbar;

@BindView(R.id.drawer_layout)
protected DrawerLayout mDrawer;

@BindView(R.id.nav_view)
protected MainNavigationView mNavigationView;

@BindView(R.id.search_view)
protected DBBookSearchView mSearchView;

private void initView() {
ButterKnife.bind(this);
}

直接在定义的时候就绑定了,貌似代码行数并没有少啊,反而还多了一些,但是不觉得看起来更清晰么?
其实 Butterknife 还可以绑定一些常用的事件,比如 onClick()onItemClick()OnCheckedChanged()等,举个栗子:

1
2
3
4
@OnClick({R.id.toolbar, R.id.drawer_layout, R.id.search_view})
public void onClick(View v) {
// TODO
}

@OnClick 注解作用就等同于 setOnClickListener(),还有其他的注解,作用类似,更多用法可以参考 Butterknife官方文档。有一个需要注意的地方是变量或类不能是 private 修饰的。

集成到项目

添加 Butterknife 到项目需要两个步骤:

  1. 在项目级别的 build.grade 添加如下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    buildscript {
    repositories {
    mavenCentral()
    }
    dependencies {
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
    }
    }
  2. 在应用级别的 build.gradle 添加如下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    apply 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. 新建一个类,里面的字段跟搜索结果对应

    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 {
    /** 请求的搜索结果数量 */
    @SerializedName("count")
    private int mCount;

    /** 搜索结果起始位置 */
    @SerializedName("start")
    private int mStart;

    /** 返回的搜索结果数量 */
    @SerializedName("total")
    private int mTotal;

    /** 搜索的图书列表 */
    @SerializedName("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;
    }

    @Override
    public String toString() {
    return "QueryDBBookRespone{" +
    "mCount=" + mCount +
    ", mStart=" + mStart +
    ", mTotal=" + mTotal +
    ", mBooks=" + mBooks +
    '}';
    }
    }

    @SerializedName() 注解是 Gson 这个库的,表明序列化的时候字段使用的名称,这个名称需要跟 json 数据里面的 key 对应。

  2. 接下来定义一个 interface

    1
    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 想要搜索的关键字
    */
    @GET("book/search")
    Call<QueryDBBookRespone> searchBooksByKeyword(@Query("q") String keyword);
    }

    @GET() 表明这个请求是 Get 方式的,类似的还是 @POST()@PUT()@DELETE() 等,里面的值为 URL 的路径,这个路径是相对的,相对于 BaseURL 的,等下就会看到了。@Query() 指明 URl 里面的参数 。如果这里不明白的建议看看这两篇博客: 你应该知道的HTTP基础知识你真的会用Retrofit2吗?Retrofit2完全教程,感谢博主。

  3. 最后就是发起请求了

    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>() {
    @Override
    public void onResponse(Call<QueryDBBookRespone> call, Response<QueryDBBookRespone> response) {
    Logger.d("query book done");
    onSearchRespone(response);
    }

    @Override
    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
    19
    public 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
2
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'

更多的使用方面参考 Retrofit官方文档,国内也有很多这方面的优秀博客。

Gson

Gson 用来解析 json 数据的,这里主要跟 Retrofit 配合使用,就不过多介绍了。你真的会用Gson吗?Gson使用指南 这里有写的很好的博客,再次感谢博主。

Fresco

Fresco 是一个图片加载库,有了 Fresco,妈妈再也不用担心图片过大出现 OOM 了,也不需要自己管理缓存方面的问题了,不管是本地还是网络的图片,一切都是那么的方便,生活是如此的美好。Fresco 缺点方面就是体积比较大,会让应用的大小增加,如果在意应用大小的,可以考虑其他的图片加载库,比如: GlideFresco 用法方面比较简单,使用 SimpleDraweeView 代替 ImageView 就差不多了,大部分需求应该都可以满足了。关于 Fresco 有一点是要特别要提一下的,这货有官方的中文版文档!!!太有良心了!英语没过四级的同学不用瑟瑟发抖了,而且 Fresco官方文档 也写的很好。这里简单记录下用法。

基本用法

  1. 初始化 Fresco,只需一次即可,在 Application 做这件事再适合不过了。

    1
    2
    3
    4
    5
    6
    7
    public class MyApplication extends Application {
    @Override
    public void onCreate() {
    super.onCreate();
    Fresco.initialize(this);
    }
    }
  2. 添加 SimpleDraweeView

    1
    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

  3. 加载图片

    1
    draweeView.setImageURI(imgUrl);
  4. 集成到项目
    在应用级别下的 build.gradle 加入如下内容:

    1
    compile 'com.facebook.fresco:fresco:0.12.0'

更多的用法参考 Fresco官方文档

推荐博文

Fresco之强大之余的痛楚

Logger

简介

Logger 是一个 Log 库,功能比 Android 自带的 Log 要强大,用过之后再也不想用回原来的 Log 了,支持输出线程、类、函数等信息,漂亮的 json 数据格式,直接跳转到源码行数等功能,使用方法和 Log 类似,更多详情见 Logger。附上几张官方的图片:

集成到项目

在应用级别下的 build.gradle 加入如下内容:

1
compile 'com.orhanobut:logger:1.15'

源码

源码在这里,欢迎 startfork