关于starTranslation

这个项目其实去年就有写了,但是那时候没有用到基类,然后用的是网易云有道翻译的sdk,耦合方面也不是做的很好,在寒假这段时间便把它重构了一遍,
同时用上了rxjava2和retorfit来进行网络的请求以及用上了ButterKnife。这个项目就当作自己的一个学习吧,后面还有什么可以优化的地方再逐步更新。

附上项目地址:starTranslation

部分知识点

Retorfit和RxJava2搭配的使用

1.创建Service类

因为要结合使用RxJava,所以返回值就不在是一个Call了,而是一个Observable。

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface networkApi {
@GET("api?")
Observable<TranslationBean> translateYouDao(
@Query("q") String q,
@Query("from") String from,
@Query("to") String to,
@Query("appKey") String appKey, //应用ID
@Query("salt") String salt, //UUID
@Query("sign") String sign, //应用ID+input+salt+curtime+应用密钥 。 input= q前10个字符+q长度+q后10个字符(q的长度>=20) 或input = 字符串
@Query("signType") String signType, //签名类型
@Query("curtime") String curtime //时间戳
);
}

2.创建请求的过程v

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
public class netWork {
private static networkApi sContactsApi;
private static OkHttpClient okHttpClient = new OkHttpClient();
private static Converter.Factory gsonConverterFactory = GsonConverterFactory.create();
private static CallAdapter.Factory rxJavaCallAdapterFactory = RxJava2CallAdapterFactory.create();

private static class ApiClientHolder {
public static final netWork INSTANCE = new netWork();
}
public static netWork getInstance() {
return ApiClientHolder.INSTANCE;
}
public networkApi getDataService() {
if (sContactsApi == null) {
Retrofit retrofit = new Retrofit.Builder()
.client(okHttpClient)
.baseUrl(Constants.BASE_URL)
.addConverterFactory(gsonConverterFactory)
.addCallAdapterFactory(rxJavaCallAdapterFactory)
.build();
sContactsApi = retrofit.create(networkApi.class);
}
return sContactsApi;
}

}

3.发出请求以及处理数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@SuppressLint("CheckResult")
public void netConnection(String q,String from,String to,String salt,String sign,String curtime){
netWork.getInstance().getDataService()
.translateYouDao(q,from,to,appID,salt,sign,signType,curtime)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<TranslationBean>() {
@Override
public void accept(TranslationBean translationBean) throws Exception {
List<TranslationBean> list_word = new ArrayList<>();
list_word.add(translationBean);
mView.showResult(list_word);
}
});
}

4.拓展

上面的写法是通过之前师兄的源码学习到的,在封装方面做的不是很好,在搜索别人的使用方法的时候找到了别人的封装方法,有时间的话需要再好好梳理下

这里是别人的写法:Android 优雅的让RxJava2.0+Retrofit2.0结合使用

关于Toolbar

Toolbar是一个很强大的控件,同时基本上每一个Activtiy都是需要它,在以前我是每个Layout都写上一个toolbar的,然后用ButterKnife初始化view,但是这样写非常麻烦……于是我将toolbar封装到了BaseActivity里,布局方面的话是先按自己的需求写一个toolbar的布局,然后在需要的地方include(viewpager的切换界面按钮我也是这样写的)。

具体的使用

首先写一个toolbar的布局

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="#1B6FB3"
android:layout_alignParentTop="true"
android:id="@+id/mtoolbar"
android:layout_height="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
</androidx.appcompat.widget.Toolbar>

接着在需要的地方include进去就好了

1
2
<include
layout="@layout/view_toolbar"/>

同样的方法还可以用来写tab栏等

room的使用

由于之前用room的时候都没有升级过数据库,所以这个坑还真是第一次踩到,在我修改了表以后根据我拙劣的英语我看懂了它需要我升级version,但在我升级version后

java.lang.IllegalStateException: A migration from 1 to 2 is necessary. Please provide a Migration in the builder or call fallbackToDestructiveMigration in the builder in which case Room will re-create all of the tables.

这是什么玩意啊???复制粘贴去google了一下,有两种办法

增加vesion,使用fallback migration 数据被清除

1
2
3
4
5
6
private static wordDatabase buildDatabase(Context context) {
return Room.databaseBuilder(context.getApplicationContext(), wordDatabase.class, "StarWord.db")
.allowMainThreadQueries()
.fallbackToDestructiveMigration() //升级仓库的时候会重建,数据会清空
.build();
}

这时候room启动时会检测版本是否有增加,如果有,那么数据库的内容会给清空,重新建表。

vesion增加,提供Migration 数据正常

我没有使用这种方法,因为我后面应该不会再修改数据库,不过还是要学习下

1
2
3
4
5
6
7
8
//添加一个version:1->2的migration
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
// 这里写表的修改
//database.execSQL("ALTER TABLE Starword " + " ADD COLUMN test INTEGER"); 给表添加一列字段,列名为test
}
};

接着把这个migration添加到databaseBuilder中

1
2
3
4
5
6
private static wordDatabase buildDatabase(Context context) {
return Room.databaseBuilder(context.getApplicationContext(), wordDatabase.class, "StarWord.db")
.allowMainThreadQueries()
.addMigrations(MIGRATION_1_2)
.build();
}

这时候数据库的表就更新了,同时旧数据也保存了下来。

自我反思

  • 在一开始,点击收藏列表的单词的时候我是准备让viewpager跳转回第一页,然后重新进行一次搜索,但是在适配器中返回的view是每个item的view,暂时没想到怎么跳转,于是才有了弹出一个Dialog的替代方法。依然还没找到解决的办法……
  • 虽然有Retorfit的数据实体类,但是我还是写了一个Room的数据类来存储数据,可以的话想写成一个类,减少代码量。
  • 一些细节没有做好,在整体上APP的生动性依然不足

先这样吧,后面还遇到什么坑的话再继续补充。