关于starTranslation

#Android#项目

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

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

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