这个项目其实去年就有写了,但是那时候没有用到基类,然后用的是网易云有道翻译的 sdk,耦合方面也不是做的很好,在寒假这段时间便把它重构了一遍,
同时用上了 rxjava2 和 retorfit 来进行网络的请求以及用上了 ButterKnife。这个项目就当作自己的一个学习吧,后面还有什么可以优化的地方再逐步更新。
附上项目地址:starTranslation
部分知识点#
Retorfit 和 RxJava2 搭配的使用#
1. 创建 Service 类
因为要结合使用 RxJava,所以返回值就不在是一个 Call 了,而是一个 Observable。
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. 创建请求的过程
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. 发出请求以及处理数据
@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. 拓展
上面的写法是通过之前师兄的源码学习到的,在封装方面做的不是很好,在搜索别人的使用方法的时候找到了别人的封装方法,有时间的话需要再好好梳理下
关于 Toolbar#
Toolbar 是一个很强大的控件,同时基本上每一个 Activtiy 都是需要它,在以前我是每个 Layout 都写上一个 toolbar 的,然后用 ButterKnife 初始化 view,但是这样写非常麻烦…… 于是我将 toolbar 封装到了 BaseActivity 里,布局方面的话是先按自己的需求写一个 toolbar 的布局,然后在需要的地方 include(viewpager 的切换界面按钮我也是这样写的)。
具体的使用
首先写一个 toolbar 的布局
<?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 进去就好了
<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 数据被清除
private static wordDatabase buildDatabase(Context context) {
return Room.databaseBuilder(context.getApplicationContext(), wordDatabase.class, "StarWord.db")
.allowMainThreadQueries()
.fallbackToDestructiveMigration() //升级仓库的时候会重建,数据会清空
.build();
}
这时候 room 启动时会检测版本是否有增加,如果有,那么数据库的内容会给清空,重新建表。
vesion 增加,提供 Migration 数据正常
我没有使用这种方法,因为我后面应该不会再修改数据库,不过还是要学习下
//添加一个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 中
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 的生动性依然不足
先这样吧,后面还遇到什么坑的话再继续补充。