Giter Site home page Giter Site logo

kunminx / jetpack-mvvm-best-practice Goto Github PK

View Code? Open in Web Editor NEW
8.7K 128.0 1.6K 10.49 MB

难得一见 Jetpack MVVM 最佳实践!在 "以简驭繁" 代码中,对 "视图控制器" 乃至 "标准化开发模式" 形成正确、深入理解!

Java 87.93% HTML 12.07%
jetpack jetpack-android mvvm mvvm-architecture mvvm-android jetpack-lifecycle-components music-player music android jetpack-navigation

jetpack-mvvm-best-practice's Introduction

《重学安卓》付费读者加微信进群:myatejx

免费试读专栏目录更新动态优惠政策

 

版权声明

我们就本项目 "被卖课" 一事,在掘金发表一期专访 《开源项目被人拿去做课程卖了 1000 多万是什么体验》

本项目系我为方便开发者们 无痛理解 Google 开源 Jetpack MVVM 中每个架构组件的 存在缘由、职责边界,而 精心设计的高频应用场景

与此同时,本项目是作为 《重学安卓》专栏 Jetpack MVVM 系列文章 “配套项目” 而存在,文章内容和项目代码设计均涉及本人对 Jetpack MVVM 独家理解,本人对此享有著作权

任何组织或个人,未经与作者本人沟通,不得将本项目代码设计和本人对 Jetpack MVVM 独家理解用于 "打包贩卖、引流、出书 和 卖课" 等商业用途。

 

架构图一览

 

前言

上周我在各大 “技术社区” 发表了一篇 《Jetpack MVVM 精讲》,原以为在 “知识网红” 唱衰 Android 的 2019 会无人问津,没想到文章一经发布,从 “国内知名公司” 架构师、技术经理,到 “世界级公司” Android 开发都在看。

且从读者反馈来看,近期大部分 Android 开发已跳出舒适圈,开始尝试认识和应用 Jetpack MVVM 到实际项目中。

只可惜,关于 Jetpack MVVM,网上多是 东拼西凑、人云亦云、通篇贴代码 文章,这不仅不能提供 “完整视角” 帮助读者 首先明确背景状况,更是给还没入门 Jetpack 读者 徒添困扰、起 劝退 作用。

好消息是,这一期,我们带着 精心打磨 Jetpack MVVM 最佳实践案例 来了!

   

爱不释手交互设计 连贯用户体验 可信源统一分发
横竖屏布局无缝切换

   

项目简介

本人拥有 3 年 “移动端业务架构” 践行和设计经验,领导或参与团队 “重构” 中大型项目多达十数个,对 Jetpack MVVM 架构在 “确立规范化、标准化开发模式 以 减少不可预期错误” 所作的努力,有深入理解。

在这个案例中,我将为你展示,Jetpack MVVM 是如何 以简驭繁 地将原本十分容易出错、一出错就会耽搁半天的开发工作,通过寥寥几行代码 轻而易举完成。

👆👆👆 划重点!

 

该项目中,

我们为 横、竖屏 场景安排两套 截然不同布局,且在 生命周期重建机制状态管理DataBindingViewModelLiveDataNavigation 等知识点帮助下,通过寥寥几行代码,轻松做到 在横竖屏两种布局间 无缝切换,且不产生任何 预期外错误

我们在多个 Fragment 页面 分别安排 播放状态指示器(包括 播放暂停按钮状态、播放列表当前索引指示 等),并向你展示 “如何” 及 “为何” 通过 LiveData 配合 可信源 ViewModel 或单例,实现 全应用范围内 “可追溯事件” 统一分发

我们在 Fragment 和 Activity 之间分别安排 跨页面通信,从而向你展示 如何基于 迪米特原则(也称 最少知道原则)、通过 UnPeekLiveData 和 应用级 SharedViewModel 实现 生命周期安全、确保消息同步可靠一致的 页面通信

我们在 ui.pagedomain.requestdata.repository 等目录下,分别安排 视图控制器、ViewModel 、Dispatcher 、DataRepository 等 内容,从而向你展示,单向依赖 架构设计,是如何通过分层 数据请求和响应,规避 “内存泄漏” 等问题。

本项目代码一律采用 经过 ISO 认证 标准化工业级语言 Java 来编写。且在上述类中,我们大都 提供丰富注释,助你理解 “骨架代码” 为何要如此设计、如此设计能 在软件工程背景下 避免哪些不可预期错误。

   

除了 在 "以简驭繁" 代码中 掌握 MVVM 最佳实践,你还可从该项目中获得内容包括:

  1. 整洁代码风格 和 标准资源命名规范。
  2. 对 “视图控制器” 知识点的 深入理解 和 正确使用。
  3. AndroidX 和 Material Design 2 全面使用。
  4. ConstraintLayout 约束布局最佳实践。
  5. 优秀的 用户体验 和 交互设计
  6. 绝不使用 Dagger,绝不使用奇技淫巧、编写艰深晦涩代码。
  7. The one more thing is:

即日起,可在 "应用商店" 下载体验!

google-play1.png coolapk1.png

   

Thanks to

AndroidX

Jetpack

material-components-android

轻听

AndroidSlidingUpPanel

项目中使用 图片素材 来自 UnSplash 提供 免费授权图片

项目中使用 音频素材 来自 BenSound 提供 免费授权音乐

   

Who is using

根据小伙伴们 “开源库使用情况” 匿名调查问卷参与,截至 2022年5月28日,我们了解到

包括 “腾讯音乐、网易、BMW、TCL” 在内诸多知名厂商软件,都参考过我们开源的此架构模式,或正在使用我们维护的 UnPeek-LiveData 等框架。

目前已将统计数据更新到 相关开源库 ReadMe 中,错过本次问卷调查的小伙伴也不用担心,我们继续对此保持开放,不定期将小伙伴们登记的公司和产品更新到表格,

以便吸纳更多小伙伴参与对 “架构组件” 的使用和反馈,集众人所长,让组件得以不断演化和升级。

https://wj.qq.com/s2/8362688/124a/

集团 / 公司 / 品牌 / 团队 产品
腾讯音乐 QQ 音乐
网易 网易云音乐
TCL 内置文件管理器
贵州广电网络 乐播播
上海亿保健康管理有限公司 安诺保
小辣椒
ezen Egshig音乐
BMW Speech
上海互教信息有限公司 知心慧学教师
美术宝 弹唱宝
网安
字节跳动直播 直播 SDK
一加手机 OPNote

   

My Pages

Email:[email protected]

Juejin:KunMinX 在掘金

《重学安卓》 专栏

付费读者加微信进群:myatejx

重学安卓小专栏

   

License

Copyright 2019-present KunMinX

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

jetpack-mvvm-best-practice's People

Contributors

dependabot[bot] avatar geertjanw avatar goooler avatar kunminx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jetpack-mvvm-best-practice's Issues

框架设计咨询

大佬可以咨询2个关于PureMusic项目的问题吗:
1) com.kunminx.binding_recyclerview.adapter.BaseDataBindingAdapter 的 viewholder中 ViewDataBinding 没有调用setLifecycleOwner(),item随着滑动被销毁不需要移除掉观察者吗

2)BaseDataBindingAdapter 中只有一个 submitList(list),只能全量替换列表,databinding中如何 只更新某个position 的item呢,以及 insert ,remove等单个操作,都是整个list替换吗?

主页旋转后返回竖屏,点击搜索按钮会崩溃

java.lang.IllegalStateException: no current navigation node
at androidx.navigation.NavController.navigate(NavController.java:824)
at androidx.navigation.NavController.navigate(NavController.java:804)
at androidx.navigation.NavController.navigate(NavController.java:790)
at androidx.navigation.NavController.navigate(NavController.java:778)
at com.kunminx.puremusic.ui.page.MainFragment$ClickProxy.search(MainFragment.java:156)
at com.kunminx.puremusic.databinding.FragmentMainBindingImpl._internalCallbackOnClick(FragmentMainBindingImpl.java:289)
at com.kunminx.puremusic.generated.callback.OnClickListener.onClick(OnClickListener.java:11)
at com.kunminx.architecture.utils.ClickUtils$1.onDebouncingClick(ClickUtils.java:357)
at com.kunminx.architecture.utils.ClickUtils$OnDebouncingClickListener.onClick(ClickUtils.java:420)

【探讨】关于依赖注入的使用

在 readme 中看到有一项说绝不使用 Dagger,但对于 jetpack 中的 hilt,请问怎么看。。。后续会加到这个项目中吗?看了官方文档,感觉 hilt 的使用相比 Dagger 方便很多,又减少了一部分样板代码,还是挺不错的,1.0.0 正式版也已经发布了

下载模拟显示问题

     我这边在模拟器里测试这个返回仍然在下载的界面
     SearchFragment
    点开“测试下载,返回页面仍有效”按钮,进度条开始动,然后我重复退出进入SearchFragment,就会发现离开页面终止的那个进度条也有数据了
    Debug断点打在getDownloadFileCanBeStoppedLiveData里,复现这个问题,但是并没有断点,很奇怪。
    换成真机到是没有出现过这个问题

netStateEvent的问题

一个request里如果有多个请求,每个请求都设置里netStateEvent。但是每个请求对netStateEvent的结果处理不一样,这样就会有问题。比例一个需要根据state显示dialog,一个需要根据state显示loading。

请教个livedata机制问题

使用了room配合livedata处理数据变动,一有数据变更就反馈到ui层,这没错,有时候一条数据某些值要变动,或者收到服务器传递过来的数据,需要修改相同的数据,会传递2次以上到ui导致adapter重复添加数据到界面上这种是要通过减少相同数据操作,还是ui上数据处理,还是把livedata换成一个子类M开头的。感觉表达起来有点问题,其实我就是想问相同数据操作数据库引起的重复通知更新,大神你是怎么处理的。

不建议直接暴露liveData的写操作

mPlayerViewModel.maxSeekDuration.set(playingMusic.getDuration());

项目看到ViewModel类只单纯持有liveData,且直接暴露liveData。
比较好的一种写法是添加Model层,例如XXXRepository或XXXModel。
所有对liveData的写操作都通过ViewModel调用Repository来写。
暴露的liveData只调用observe方法。
不然写操作多的话,遍地的liveData的set会导致很难维护。

可能项目里liveData数据结构简单所以感知不是特别大。

关于架构设计的一个疑问

首先,先为作者的详细注释点个赞,毕竟能详细到每一步怎么设计怎么考虑的入门项目确实少;

不过因此,我在看 ViewModel的时候产生了一个疑问:

谷歌关于Jetpack的移动架构指南(https://developer.android.google.cn/jetpack/guide 中构造界面那部分) 中是这么规定ViewModel的作用的:

ViewModel 对象为特定的界面组件(如 Fragment 或 Activity)提供数据,并包含数据处理业务逻辑,以与模型进行通信。例如,ViewModel 可以调用其他组件来加载数据,还可以转发用户请求来修改数据。ViewModel 不了解界面组件,因此不受配置更改(如在旋转设备时重新创建 Activity)的影响。

也就是说,ViewModel 应该也负责业务逻辑;

但是我看项目中任何一个继承ViewModel的类都不负责任何业务上的逻辑,比如说state的下面的只进行状态存储,那个SharedViewModel也只是为了实现 唯一可信源

比如说state下的注释中明确规定了不会有业务方面的逻辑

此外,state-ViewModel 的职责仅限于 状态托管,不建议在此处理 UI 逻辑, UI 逻辑只适合在 Activity/Fragment 等视图控制器中完成,是 “数据驱动” 的一部分, 将来升级到 Jetpack Compose 更是如此。

所以问题来了

为什么违背谷歌设计的建议而设计目前这样的架构呢?是有什么特殊使用场景需求还是?这么设计的原因和目的是?如果没有什么特殊需求的话,应该怎么设计架构?

Could not resolve all dependencies for configuration ':architecture:_internal_aapt2_binary'

clone下来无法正常运行,关了翻墙也还是这样,是我的环境的问题吗?

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':architecture:compileDebugLibraryResources'.
> Could not resolve all dependencies for configuration ':architecture:_internal_aapt2_binary'.
   > org.apache.commons.logging.LogConfigurationException: No suitable Log constructor [Ljava.lang.Class;@23c916c2 for org.apache.commons.logging.impl.Log4JLogger (Caused by java.lang.NoClassDefFoundError: org/apache/log4j/Category) (Caused by org.apache.commons.logging.LogConfigurationException: No suitable Log constructor [Ljava.lang.Class;@23c916c2 for org.apache.commons.logging.impl.Log4JLogger (Caused by java.lang.NoClassDefFoundError: org/apache/log4j/Category))

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 6s

想知道怎么在列表中增加多种样式的item

目前adapter中关于ViewDataBinding的泛型其实是对应着holder的布局(因为holder在进行绑定的ui的时候会使用到此ViewDataBinding),假如一个列表中存在多种holder那该怎么处理ViewDataBinding的问题呢

您这个架构的一个目的是保持Activity或Fragment中不出现DataBinding中的内容,但是如果要配置一些组件的程序,比如viewPager2要使用TabLayoutMediator,需要进行acctch() 和detach()的调用,也就是要绑定周明周期,这种情况需要怎么处理呢

您这个架构的一个目的是保持Activity或Fragment中不出现DataBinding中的内容,但是如果要配置一些组件的程序,比如viewPager2要使用TabLayoutMediator,需要进行acctch() 和detach()的调用,也就是要绑定周明周期,这种情况需要怎么处理呢

获取结果没有双向无感知

返回的数据Flowable有改变没有考虑到只会刷新一次 以及UI与数据层双向无感知 databing 有部分问题 切入性大

多页面下如何该编写登录逻辑?

目前项目只有少量的页面,所以登录相关的问题不大。但页面多了,登录就复杂了。
1.navigation不支持拦截,所以没法设置统一登录
2.navigation跳转需要写action,如果导航xml每个fragment下都写一个登录的action,那需要写很多。

基于上面2个条件,请教一下作者,在稍微大一点的项目里面,登录拦截这块应该如何规划比较好。

底部播放器提示风险警告水印:”PlayerFragment 未遵循 Databinding 严格模式,存在 null 安全风险“

作者你好,将项目加载到手机上后,布局 fragment_player 左上角出现不可消除的警告提示:”PlayerFragment 未遵循 Databinding 严格模式,存在 null 安全风险“。拆解后,应该是 PlayerFragment.java 中调用 (FragmentPlayerBinding) getBinding(),所致。请问使用系统生成的 databindingimpl 操作控件就会出现此警告吗,并且这种水印应该怎么消除呢,多谢。

ViewDataBinding 不暴露给实现Activity问题

ViewDataBinding 不暴露给实现Activity问题

比如xml中定义的TabItem,它的onClick事件无法通过databinding实现,如果用了会报空指针异常。。 这时就要在自己实现的Acitivity中 取到TabItem , 对它进行点击事件处理

【Bug】从通知点击进入 MainActivity 发生 Crash

复现方法:MainActivity 在前台,点击播放音乐,下拉通知栏,点击通知进入 MainActivity
出现概率: 100%

Stacktrace:
com.kunminx.puremusic E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.kunminx.puremusic, PID: 2055
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.kunminx.puremusic/com.kunminx.puremusic.MainActivity}: java.lang.IllegalArgumentException: Cannot add the same observer with different lifecycles
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.IllegalArgumentException: Cannot add the same observer with different lifecycles
at androidx.lifecycle.LiveData.observe(LiveData.java:197)
at com.kunminx.architecture.bridge.callback.UnPeekLiveData.observe(UnPeekLiveData.java:39)
at com.kunminx.puremusic.ui.base.BaseActivity.onCreate(BaseActivity.java:52)
at com.kunminx.puremusic.MainActivity.onCreate(MainActivity.java:43)
at android.app.Activity.performCreate(Activity.java:7801)
at android.app.Activity.performCreate(Activity.java:7790)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) 
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 
at android.os.Handler.dispatchMessage(Handler.java:107) 
at android.os.Looper.loop(Looper.java:214) 
at android.app.ActivityThread.main(ActivityThread.java:7356) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

我认为这里是因为 MainActivity 没有设置启动模式,导致重复初始化了,加上了 SingleTask, SingleTop, SingleInstance 都可以解决此问题,但我隐约觉得这个不是 root cause。

LifeCycle 库用得不多,请大佬给解释一下这个问题。

关于Navigation

看您的项目,从MainFragment->LoginFragment,的确MainFragment没有走onDestoyView
但是小的copy了architecture模块下navigation.fragment整个包到新项目,从
AFragment->BFragment,A就发生了onDestoryView。我看了下路由没啥异,是要有什么额外的设置才能让A不销毁视图吗?很疑惑,望解答

探讨页面成员变量的保存和恢复

@KunMinX
理解了,我看了下配置发生变化时保存的具体对象是viewModelStore,这个对象具体activity的属性,它有个属性mMap,存储了所有的viewModel,通过ViewModelProvider.get()方法时,先获取最后配置变化的viewModelStore,然后从mMap中获取viewModel.理解了这个原理,也有一个小想法,就是viewModelStore是activity的对象,配置发生变化时,因为viewModelStore被保存下来了,所以旧的activity回收不了,感觉也是一个内存泄漏.

Originally posted by @hanshengjian in #41 (comment)

【 提问须知 】

如有 bug,请另外 new 一个 issue ⚠️⚠️⚠️

本项目开 issue 规范:

  1. 有任何 bug 都欢迎及时开 issue,我看到后予以处理。
  2. 如有使用上的疑问,请先认真阅读 Readme 和源码 sample,在没有找到答案后,另外开 issue。
  3. 如开 issue 是为了发表个人见解,请务必 客观、具体、严谨;严禁草率、乱入、带节奏:

务必注明观点所对应的场景,并附上完整可复现的代码,

不然缺乏一致的前提依据来有效交流!

任何缺乏实证依据和因果逻辑的泛泛而谈,都可能对其他使用者造成困扰。

在发表个人见解前,请先确保自己认真阅读过源码。这是对自己、对作者、对其他读者最起码的尊重。

想请教一下 PlayerFragment 的正确写法应该是怎样的呢 ?

看了一下 issue ,貌似没人提这个问题 ……

如果按照打开抽屉栏相同的思路(MainActivity 与 MainFragment 使用 SharedViewModel 进行信息传递),那 PlayerFragment 滑动时控件的移动应该是 (MainActivity 与 PlayerFragment 使用 SharedViewModel 进行信息传递)。

可以做一个 EventHandler 实现 SlidingUpPanelLayout.PanelSlideListener ,在 MainActivity 中将观察到的滑动百分比记录给 SharedViewModel ,在 PlayerFragment 中对 SharedViewModel 该百分比进行观察,对应调整 PlayerFragment 中控件的位置或透明。

如果不在 PlayerFragment 中使用 getBinding() 方法获取 viewBinding ,那应该如何初始化工程中 PlayerSlideListener 这个类呢 ?

感觉也可以将每个需要改变的控件做一个 BindAdapter 方法,将单个控件与观察到的百分比在 layout/fragment_player 中进行绑定,但有些时候要考虑父View 的大小;PlayerSlideListener 中还有个 mStatus (当然这个可以放在 PlayerFragmentViewModel 中),总体来说这样肯定不如写成一个类 PlayerSlideListener 整体控制好一点。

所以想知道下规范的写法,这里应该是怎样的 ?

对ViewModel的一些疑惑

  • ClickProxy能不能写在VM,我直接设置liveData值,然后试图控制器里去观察是不是也可以呢?
  • Model应该只能VM去引用吧?那这样的话,视图控制器直接去观察ModelliveData,这样有没有违背这个原则。比如在 MainFragment onViewCreated
    PlayerManager.getInstance().getChangeMusicLiveData().observe()

期待解答传道 :),感谢!

关于网络请求

我在OKHttp build中使用到持久化Cookie,所以在build过程中需要用传入Context ,那么我在ViewModel请求网络过程中也要传入Context, 这样好像违背了MVVM..不知道该如何解决

wrong link for playstore

The link for the playstore is the same as the link for coolapk in the Readme File on line 83
[![google-play1.png](https://upload-images.jianshu.io/upload_images/57036-f9dbd7810d38ae95.png)](https://www.coolapk.com/apk/247826)

Cannot add the same observer with different lifecycles

我使用了您的BaseActivity,有多个Activity都继承了BaseActivity,我在使用的时候报错
java.lang.IllegalArgumentException: Cannot add the same observer with different lifecycles
找到原因代码
NetworkStateManager.getInstance().mNetworkStateCallback.observe(this, netState -> {
//TODO 这里可以执行统一的网络状态通知和处理

    });

如果有多个Activity,如何正确的使用BaseActivity呢

SharedViewModel类中使用UnPeekLiveData的构造器方法报错的问题

您提交的646a58de记录中修改UnPeekLiveData构造器的方式后,调用的地方未进行变更,请知悉

  • SharedViewModel类
public static final UnPeekLiveData<Boolean> ENABLE_SWIPE_DRAWER =
           new UnPeekLiveData.Builder<Boolean>().setEventLiveTime(500).create();
  • UnPeekLiveData.Builder类中原有方法已经变更为下列方法
public Builder<T> setEventSurvivalTime(int eventSurvivalTime) {
        this.eventSurvivalTime = eventSurvivalTime;
        return this;
}

ShareViewModel的一些疑问

作者你好,这套框架非常好,有很多值得思考的地方。
不过有个疑问,假设有一模块既不是Activity也不是Fragment的域使用到ShareViewModel的数据时,应该如何获取会是比较好的方案呢?

闪退

应该是appcompat版本问题,看错题提示是webview报错了

怎么理解状态管理分治

请问这句话“MVP 的 Presenter 和 MVVM - Clean 的 ViewModel 都不具备状态管理分治的能力”怎么理解

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.