這個項目其實去年就有寫了,但是那時候沒有用到基類,然後用的是網易雲有道翻譯的 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 了一下,有兩種辦法
增加 version,使用 fallback migration 數據被清除
private static wordDatabase buildDatabase(Context context) {
return Room.databaseBuilder(context.getApplicationContext(), wordDatabase.class, "StarWord.db")
.allowMainThreadQueries()
.fallbackToDestructiveMigration() //升級倉庫的時候會重建,數據會清空
.build();
}
這時候 room 啟動時會檢測版本是否有增加,如果有,那麼數據庫的內容會給清空,重新建表。
version 增加,提供 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 的生動性依然不足
先這樣吧,後面還遇到什麼坑的話再繼續補充。