在此非常感谢鸿洋大神提供的 WanAndroid API
该项目基于「玩 Android 接口」接口,整体采用 MVVM, Android Jectpack, Retrofit, Kotlin 协程进行编写。 是由 kukyxs 和 Taonce 一起编写完成,目前已完成所有的开发功能,细节有待调整。
起因
说起一起开源这个项目的初衷,总结来说是缘于学习和熟悉 Jetpack 和协程知识,结果在过程中一步一个雷,雷的体无完肤。从零到1.0版本诞生总共历时一个月,时间不算长但是收获很多,能进一步的对协程和 Jetpack 的使用加深理解,下面是该项目的地址,如果你对本项目感兴趣或者认为本项目还不错的还请点个 star:
1.0 版本的诞生
项目于8月6日 released 1.0版本,实现了 WanAndroid API 的基本功能,8月8日优化体验之后,released 1.0.1版本。下面介绍下目前实现的功能:
- 注册和登录
- 首页最新博文和 Banner 图
- 项目分类
- 学习体系分类
- 公众号分类和公众号文章列表
- 文章详情查看
- 文章收藏和取消收藏
- TODO待办
- 搜索功能
以下是 WanAndroid 客户端的界面截图:
技术点介绍
- 协程
用来代替 RxJava,处理异步操作,它可以让开发者体会到以同步的方式去实现异步操作。不过在该项目中有的地方还是结合了协程 + 回调的形式,蜜汁尴尬 -,暂时没想到有什么好的解决方案。下面这段代码是通过协程 + Retrofit
进行网络请求。
// 加载首页置顶文章
suspend fun loadTops(): List<ArticleDetail>? = withContext(Dispatchers.IO) { RetrofitManager.apiService.topArticle(PreferencesHelper .fetchCookie(WanApplication.instance)).data
}
- Jetpack 系列
- DataBinding
最大的好处就是大幅度的节约了UI控件的设置代码,不需要在 V 层去设置某个控件的点击事件或者属性等,我们可以更专注的去写业务逻辑代码。
不过它的劣势也很明显,在 xml
文件中新增 DB
属性之后需要 build 下工程,假如出现错误了,有时候报错的信息也很模糊...
下面的这段代码是通过 DataBinding
来绑定 RecyclerView
的点击、长按事件和 Adapter
属性,写起来非常舒服。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:bind="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="adapter"
type="androidx.paging.PagedListAdapter" />
<variable
name="itemClick"
type="com.kuky.demo.wan.android.base.OnItemClickListener" />
<variable
name="itemLongClick"
type="com.kuky.demo.wan.android.base.OnItemLongClickListener" />
</data>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/article_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adapter="@{adapter}"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:scrollbars="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
bind:hasFixedSize="@{true}"
bind:pageItemClick="@{itemClick}"
bind:pageItemLongClick="@{itemLongClick}"
tools:itemCount="20"
tools:listitem="@layout/recycler_home_article" />
</layout>
- Lifecycle + ViewModel
Lifecycle 可以对 Activity
或者 Fragment
的生命周期进行感应,ViewModel 继承了 Lifecycle 此特性,并且通过对内部不可见 Fragment
的持有,从而拥有屏幕在横竖屏切换的时候数据不丢失的特点。
- LiveData
LiveData 在被推出的时候并不引人注目,总觉得他很鸡肋,它能实现的 RxJava 都能实现,相反并不可以。不过随着 LiveData 对 DataBinding 、Paging 和 Room 的原生支持,使它有了立足之地。通过和 DataBinding 的结合,可以达到数据变化后自动更新UI的操作,而且我们也可以在主线程或者子线程更新数据,只需要通过 setValue()
或者 postValue()
就能完成。
这里就不列代码出来了,代码都是比较分散的,大家可以去项目中逐一查看。
- Paging
一个能让 RecyclerView
连续加载的狂热分子,能让用户体会到丝滑般的滑动效果,并且它还可以直接结合 LiveData 和 DiffUtil 使用,更是香喷喷,无奈再香的东西它的坑还是存在的,你说你能结合 LiveData 使用是多么好的事,为啥在数据在返回的时候你传个空列表嘛意思么,延时去取数据?
var articles: LiveData<PagedList<ArticleDetail>>? = null
fun fetchHomeArticle() {
articles = LivePagedListBuilder(
HomeArticleDataSourceFactory(repository),
PagedList.Config.Builder()
.setPageSize(20)
.setEnablePlaceholders(true)
.setInitialLoadSizeHint(20)
.build()
).build()
}
通过返回 LiveData
类型的值,然后再 observer{}
,这时候你就会不由自主的发出真香的感叹!
- Navigation
Google官方**单 Activity 多 Fragment 的架构组件,为了让开发者更好的处理 Fragment
之间的跳转问题,项目一开始也是秉承着单 Activity 多 Fragment **的原则去进行编写,在1.0之前都是采用的这种模式,不过在1.0.1版本将启动页换成了 Activity
,原因在于无法处理启动白屏的问题。
fun viewDetail(controller: NavController, @IdRes id: Int, url: String) {
if (url.isBlank()) return
controller.navigate(id, Bundle().apply { putString("url", url) })
}
总结
如果你看到这里,那么对 CoroutinesWanAndroid 已经了解的差不多了,这个项目还是有很多新颖的知识点和技术,如果你对 Kotlin、协程 或者 Jetpack 系列感兴趣的话,还是非常推荐你了解下这个项目。在了解的过程中,如若对项目存在什么疑问和见解,欢迎提出你的 Issues