WanAndroid
WanAndroid copied to clipboard
Coroutines+MVVM+Material Design玩安卓客户端
重置的项目地址为:https://github.com/ShowMeThe/MaterialWanAndroid
(基本上的功能都完成了,有问题的留下issue, 改了UI,多了个皮肤切换,和修复部分bug)
记录:2020/3/29 WanAndroid客户端也重置了不少内容,包括页面等等,并加入了无缝切换控件颜色,换肤功能,基于DataBinding下进行统一管理,并且支持自定义的控件,先看看图,那边的READ.MD等我写得差不多后再更新。大致图如下:

记录:2020/3/24 (暂定的临时解决方案,还是存在使用上的不便,这时最好方法是不要用这个VMRouter)修复严重bug,会导致利用VMRouter这个类请求VM方法,如果是带了网络请求,并用了CallResult,某种场景下必定会错
VMRouter这个类中 在Fragment下原代码初始化
router = VMRouter(viewModel,this)
改为
router = VMRouter(viewModel,activity)
此时这个VMRouter(private var viewModel: ViewModel,var owner: LifecycleOwner?) 此时owner会因为被替换了导致使用了CallResult的必定出错
类似场景如下:
Activity + ViewPager ,此时 ViewPager里有两个Fragment,FragmentA(index = 0),FragmentB(index = 1),然后默认进入看到FragmentB,在FragmentB中加载一个子Fragment共享同一个VM,然后popback推出栈,再滑动到FragmentA 就会导致出错。
记录:2020/3/11
该版本玩安卓客户端将在未来一段时间内进行重置,包括UI和交互动画,将无关紧要花里胡哨的效果去掉 将以MaterialTransition+Fragment为主,修改以前没发现一些Bug,把png替换成VectorDrawable,重置完成时间不定
简书地址:https://www.jianshu.com/p/03e7446ff512
项目中用到的FloatActionButton和Banner:
Banner: https://github.com/ShowMeThe/BannerView FloationActionButtonExpandMenu:https://github.com/ShowMeThe/SpeedDial
新的UI
基于AAC架构玩安卓客户端
首页、公众号、知识体系、项目
网络请求
还是常用大名鼎鼎的Retrofit2,然后结合了coroutines,使用起来更加方便了
举个栗子:
接口只需要使用suspend即可
@FormUrlEncoded
@POST("user/login")
suspend fun login(@Field("username") username:String,@Field("password") password:String) : Response<JsonResult<Auth>>
处理请求的逻辑封装了另一个类CallResult,只显示关键部分
fun hold(result: suspend () -> Response<JsonResult<T>>): CallResult<T> {
var response: Response<JsonResult<T>>?
var netJob: Job? = null
owner?.apply {
netJob = lifecycleScope.launchWhenStarted {
__________ 处理loading状态 ————————————————
response = withContext(Dispatchers.IO) {
withTimeoutOrNull(10000){//超时处理
result.invoke() //网络请求
}
}
if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
withContext(Dispatchers.Main) {
__________ 处理超时和返回结果的逻辑————————————————
}
} else {
netJob?.cancel()
}
}
}
return this
}
使用方式如下:
fun login(username:String,password:String,call:MutableLiveData<Result<Auth>>){
CallResult<Auth>(owner){
loading {
__________ 处理读取————————————————
}.success { result, message ->
__________ 处理成功————————————————
call.value = result
}.error { result, code, message ->
__________ 处理错误————————————————
call.value = result
}.outTime {
__________ 处理超时————————————————
call.value = it
}.hold {
api.login(username, password)//登录
}
}
}
该项目使用: LiveData、ViewModel、Room 、Databinding 、WorkManager 、Lifecycles
图片加载采用: Glide
消息总线采用了:live-event-bus github:https://github.com/JeremyLiao/LiveEventBus
使用到了SlideBack的返回动画,fork后我进行进修改,原项目github:https://github.com/ParfoisMeng/SlideBack
其中照片墙部分不属于玩安卓的内容,是我本人自行加上,属于本地内容,利用Room数据库完成基本的数据获取。
超时处理
首页的文章图片新增了超时处理的代码,但由于有缓冲和wanandroid Api反应快,效果不明显,测试起来比较麻烦,直接看日志或者打断点比较好校验, 也可以自己在电脑起一个接口,设置等待时长来测试。至于网络不好,超时后重新提交的设计暂时不加入。不过这个功能在传统的Rxjava2+Retrofit实现起来很方便的。
增加了快捷标签的入口
更新日志
V1.05 修改时间:2019/12/4
内容:逐步进行DSL化,并把Retrofit的接口进行单例
一、Retrofit的接口进行单例(—————其实这种单例是很简单,我都不知道我当时写的时候为啥搞得那么复杂——————)
例子:
___________________初始化_______________
startInit {
modules(Module{
single{ RetroHttp.createApi(auth::class.java) }
},
Module{
single{ RetroHttp.createApi(main::class.java) }
})
}
————————————————调用得地方————————————
val api: main by inject() //获取main.class的实例
二、修改了TextWatcher
fun EditText.textWatcher(textWatch: SimpleTextWatcher.()->Unit){
val simpleTextWatcher = SimpleTextWatcher()
textWatch.invoke(simpleTextWatcher)
addTextChangedListener(object :TextWatcher{
override fun afterTextChanged(s: Editable?) {
simpleTextWatcher.afterText?.invoke(s,s) }
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
simpleTextWatcher.beforeText?.invoke(s, start, count, after) }
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
simpleTextWatcher.onTextChanged?.invoke(s, start, before, count) }
})
}
class SimpleTextWatcher() {
var afterText: (Editable?.(s: Editable?)->Unit)? = null
fun afterTextChanged(afterText: (Editable?.(s: Editable?)->Unit)){
this.afterText = afterText }
var beforeText:((s: CharSequence?, start: Int, count: Int, after: Int)->Unit)? = null
fun beforeTextChanged(beforeText:((s: CharSequence?, start: Int, count: Int, after: Int)->Unit)){
this.beforeText = beforeText }
var onTextChanged : ((s: CharSequence?, start: Int, before: Int, count: Int)->Unit)? = null
fun onTextChanged(onTextChanged : ((s: CharSequence?, start: Int, before: Int, count: Int)->Unit)){
this.onTextChanged = onTextChanged}
}
V1.05 修改时间:2019/11/14
内容:重构了登录和注册UI
V1.03 修改时间:2019/11/10
内容:添加一个预加载占位的drawable,尚未完善优化,效果如下
V1.03 修改时间:2019/11/7
内容:修复冷启动慢得问题,在启动时候,使用了反射来解决权限申请问题,此处是很大的问题,再加上Kotlin的Reflect比Java的Reflect还慢
导致启动到看到SplashActivity高达2s之久。
V1.03 修改时间:2019/11/2
内容:新增一个FloatActonButton的菜单,实现的效果其实不难,效果如下:
简单说一下步骤吧,地址:https://github.com/ShowMeThe/SpeedDial
1、通过自定义的Beahavior 可以很简单地拿到需要依附的View
override fun layoutDependsOn(parent: CoordinatorLayout, child: ExpandMenuChildLayout, dependency: View): Boolean {
return dependency is FloatingActionButton
}
2、对自己控制的view和依附的dependency构建关系,相对位置,状态改变监听等等,代码在ExpandBottomBehavior.kt里
override fun dependentViewChanged(parent: CoordinatorLayout, child: CircularRevealLinearLayout, dependency: View) {
val dependencyWidth = dependency.measuredWidth
val dependencyHeight = dependency.measuredHeight
val childHeight = child.measuredHeight
val childWidth = child.measuredWidth
val dependencyX = dependency.x
val dependencyY = dependency.y + dependencyHeight
child.x = dependencyX + dependencyWidth - childWidth
child.y = dependencyY - defaultMargin - dependencyHeight - childHeight
}
3 、就是在这个view上实现常规自定view代码编写,其实核心是需要理解Beahavior的用处,CoordinatorLayout里面这个是一个很灵活的操作,
网上有非常多的例子介绍怎么使用,也是很常规的例子。
然后略改了一下之前添加Glide图片加载效果,让图片加载过渡时候有个渐变色效果,代码如下:
override fun transition(current: Drawable, adapter: Transition.ViewAdapter): Boolean {
var previous = adapter.currentDrawable
if (previous == null) {
previous = ColorDrawable(Palette.from(createBitmap(current)).generate().getVibrantColor(Color.TRANSPARENT))
}
—————————— 一堆实现动画的代码 ——————————
return true
}
private fun createBitmap(current: Drawable) : Bitmap{
val bitmap = Bitmap.createBitmap(10,10,Bitmap.Config.RGB_565)
val canvas = Canvas(bitmap)
current.setBounds(0,0,10,10)
current.draw(canvas)
return bitmap
}
V1.03 修改时间:2019/10/29
内容: 新增一个可以监听到下载进度的ImageView,继承PhotpView,利用onDraw,画出进度条。新增Glide的Okhttp3图片Loader的自定义进度监听。 自定义属性为zoomable,默认为false 新增一个注解的权限管理,利用Fragment处理权限申请。在权限申请的内部,仅提供了申请结果。暂不实现权限被拒绝后吊起一个对话框告知用户手动申请, 个人理由是因为在权限开发这块我们更应该倾向于某功能需要用到权限时候才执行权限申请,而不是一次性全部申请。所以应该是尽可能保留功能稳定完善, 减少提示框的弹出。
V1.02 修改时间:2019/10/25
内容:修复Glide的过渡动画,会导致某些时候图片加载完后,被拉伸了。 修改图片墙的FAB位置