Magren

Magren

Idealist & Garbage maker 🛸
twitter
jike

关于starTranslation

这个项目其实去年就有写了,但是那时候没有用到基类,然后用的是网易云有道翻译的 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. 拓展

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

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

关于 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 的生动性依然不足

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

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。