这个项目其实去年就有写了,但是那时候没有用到基类,然后用的是网易云有道翻译的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是一个很强大的控件,同时基本上每一个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 static final Migration MIGRATION_1_2 = new Migration (1 , 2 ) { @Override public void migrate (SupportSQLiteDatabase database) { } };
接着把这个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的生动性依然不足
先这样吧,后面还遇到什么坑的话再继续补充。