Coder Social home page Coder Social logo

hegaojian / jetpackmvvm Goto Github PK

View Code? Open in Web Editor NEW
3.0K 45.0 595.0 81.68 MB

:chicken::basketball:一个Jetpack结合MVVM的快速开发框架,基于MVVM模式集成谷歌官方推荐的JetPack组件库:LiveData、ViewModel、Lifecycle、Navigation组件 使用Kotlin语言,添加大量拓展函数,简化代码 加入Retrofit网络请求,协程,帮你简化各种操作,让你快速开发项目

Home Page: https://github.com/hegaojian/JetpackMvvm

License: Apache License 2.0

Kotlin 88.60% Java 11.40%
mvvm jetpack viewmodel lifecycle databinding livedata retrofit kotlin okhttp mvvm-jetpack

jetpackmvvm's Issues

能够多增加点测试用例

我搜索到的开源项目测试用例都少的可怜,不知道是不是我得姿势不对。希望能补充些测试用例,很想知道android工程师开发应用时如何进行自测

关于多个fragment共用一个viewmodel的情况

me.hgj.jetpackmvvm.demo D: loginFragment--------->onCreate
me.hgj.jetpackmvvm.demo D: loginFragment--------->onStart
me.hgj.jetpackmvvm.demo D: loginFragment--------->onResume
me.hgj.jetpackmvvm.demo D: loginFragment--------->LoginRegisterViewModel@5df2ec
me.hgj.jetpackmvvm.demo D: loginFragment--------->RequestLoginRegisterViewModel@68c86b5
me.hgj.jetpackmvvm.demo D: RegisterFrgment--------->onCreate
me.hgj.jetpackmvvm.demo D: RegisterFrgment--------->onStart
me.hgj.jetpackmvvm.demo D: RegisterFrgment--------->onResume
me.hgj.jetpackmvvm.demo D: RegisterFrgment--------->LoginRegisterViewModel@b754ad6
me.hgj.jetpackmvvm.demo D: RegisterFrgment--------->RequestLoginRegisterViewModel@5424157

我注意到LoginFragment和 RegisterFrgment 共用了2个ViewModel,但是因为是使用getViewModel(获取当前fragment上下文的方法)获取的,所以这两个ViewModel并不是同一个对象。
假设我在LoginFragment和RegisterFrgment 的RequestLoginRegisterViewModel都内持有了数据库的操作对象,那么我在RegisterFrgment 被销毁的时候回调rViewModel的onCleared()中把它close了。那么会影响到LoginFragment的RequestLoginRegisterViewModel内的数据库的操作对象吗?

提个bug,拦截返回事假会使 其他的fragment无法通过onBackPressedDispatcher拦截返回事件

    override fun onBackPressed() {
        val nav = Navigation.findNavController(this, R.id.nav_host_fragment)
        if (nav.currentDestination != null && nav.currentDestination!!.id != R.id.mainFragment) {
            //如果当前界面不是主页,那么直接调用返回即可
            nav.navigateUp()
        } else {
            //是主页
            if (System.currentTimeMillis() - exitTime > 2000) {
                ToastUtils.showShort("再按一次退出程序")
                exitTime = System.currentTimeMillis()
            } else {
                super.onBackPressed()
            }
        }
    }

这样子重写MainActivity的onBackPressed()方式拦截返回事假会使 其他的fragment无法通过onBackPressedDispatcher拦截返回事件。
参考:https://developer.android.google.cn/guide/navigation/navigation-custom-back#kotlin
参考:https://www.jianshu.com/p/aec2cde0a5f0

我目前是在MainFragment添加onBackPressedDispatcher拦截返回键,处理返回2次退出app事件
在SubFragment添加onBackPressedDispatcher,拦截返回键,处理之前提到的Navigation 的出栈事件

关于在viewModel 之外请求数据的情况

在我的实际使用中,有的页面因为功能比较杂,导致在 viewModel 之外需要请求数据,偏偏请求数据的这个文件已经 继承了其他的类了,无非再次继承 viewModel,这样一来,哪怕在这个文件中 new ViewModel 也不行,发起请求后的回调就回不去了。个人比较菜,所有咨询下大佬这种情况有什么好一点的解决办法。

给菜鸡作者提个bug

Demo中进入SettingFragment(设置界面)后,不管做什么操作,退出该Fragment后,操作其他的任何界面变多了以后会变的卡顿(可以试试项目模块)......如果直接写一个SettingActivity去包裹SettingFragment,退出该SettingActivity就不会有卡顿的问题。
目前发现原因大概是PreferenceFragmentCompat该类的锅,记录一下放在这里,大家如果发现有好的解决方案也可以提一下

kotlin-android-extensions转viewbinding

谷歌残忍的抛弃了kotlin-android-extensions,鸡哥是否有计划把项目里的kotlin-android-extensions转成viewbinding?
主要是我自己太菜了,不知道怎么改。。所以想看下大佬的代码然后ctrl+C,ctrl+V一下

作者为何用AndroidViewModel?

之前一直关注作者写的demo,今天下了新demo看,改动好大啊,尤其是新的BaseViewModel。并没有看到在ViewModel里用到application。再就是初始化viewmodel的方式着实累了点。可以参考private val requestViewModel :RequestAriticleViewModel by viewModels(),直接使用ktx中的扩展函数就好。

大佬,关于livedate更新数据的回调的问题请教一下

我看项目使用livedata更新数据,是在外面有包装了一层ListDataUiState or UpdateUiState。如果是列表还好,如果出现异常,可以使用arrayListOf()设置默认值,但是UpdateUiState如果请求时出现异常,那包装成UpdateUiState对象,data该怎么穿,我尝试设置成data: T?和T: Any都不行,我看项目中data类型全都是Int,可以设置0,我的都是数据类型,不知道该怎么穿,麻烦大佬看一下

网络请求返回的 data 为 null 时奔溃

首先感谢大佬的框架,集成到项目中挺方便的。最近在使用中碰到一些问题,咨询一下。
1.我这边返回的数据格式就是那种有 code,message,data 的样子
2.所以我网络请求一般都是用自动脱壳的方式,但是这边有个问题是,当返回的数据 data 是 null的时候,app就会奔溃
报错信息:
java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter it

此处的 it 是请求成功后,在 parseState(resultState,{ 这里的it })
3. 用不脱壳的方式应该是ok的,因为自己可以处理进行判空呀啥的。但是所有的请求接口,总会有的接口有时候返回 null 有时候有数据,这样的话岂不是所有的接口都需要使用不脱壳的方式嘛。
4.咨询一下大佬有没有更好的解决方式,或者怎么弄会更合理

目前被修改过的Navigation是否能做到类似replace的功能

比如有 A . B . C . D 四个fragment。
正常跳转的话的 A ->B ->C ->D
此时的回退栈:
A --B--C--D

如果有个场景是 A ->B -替换->C-替换->D
此时的回退栈:
A -- D

如果拿作者的demo举例子的话就是
首页 --> 搜索页 -->搜索结果页

如果要求 [搜索页] 点击搜索跳转到 [搜索结果页] 后, [搜索页]从回退栈中移除
此时的回退栈
首页 --搜索结果页

类似淘宝 京东的搜索页都是这样的逻辑

我看了官方的Navigation文档,google推荐是使用popUpTo 和 popUpToInclusive来清除当前页和目标页面之间的栈元素。但是感觉使用起来还需要拦截回退事件,不够自然

作者有什么建议或者思路呢

希望和作者讨论一下关于Navigation 的问题

最近项目已经快完工了。但是在这段时间的开发中发现Navigation 在某些需求上会有一些缺陷。

项目内集成了网易云信,作为即时IM的库。网易提供了一个UI库,其中【聊天会话】是一个Activity。这就很尴尬了。

目前使用Navigation 的时候。app基本就是一个MainActivity。然后在上面加了一个mainfragment+viewpager2.

在从mainfragment跳转到【聊天会话Activity】后。如果就只在【聊天会话Activity】一个页面还好。但是出现了一个十分难办的需求。

【聊天会话Activity】 ---> productFragment——>favoriteFragment 这种聊天过程中点击某个对话气泡跳转的具体页面的需求。

productFragment和favoriteFragment都是在MainActivity上面Navigation导航图内的页面。

目前我只能新建了一个【TempActivity+tempFragment】,再在上面弄一个Navigation导航图,把productFragment和favoriteFragment复制一份添加上去。

然后形成了【MainActivity+mainfragment】---->【聊天会话Activity】--->【TempActivity+tempFragment】

这样变扭的形式。

老实说我知道这样的实现很蠢,但是确实遇到了这个难题。

目前只能打算在项目上线之后再慢慢把【聊天会话Activity】用fragment实现,纳入【MainActivity+mainfragment】的体系。

不知道如果是作者你遇到这种情况,会怎么处理

关于网络请求,后台数据请求code 200 data为空的时候出错

用了你的框架来重构 发现 后台如果没设置参数data为空的时候 由于kotlin的原因 用BaseViewModel.request请求 在BaseViewModelExt.kt解析数据的时候 会报出 Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter it的错误
如果用requestNoCheck来请求 在解析又会多一步操作来处理 -0 - 不用想用这个方法 。
请问有什么办法来处理这个问题吗

ResultState包装对象后,只能在observe拿到数据吗?

比如我在viewmodel中定义了titleData,我会多次调用getProjectTitleData这个接口
var titleData: MutableLiveData<ResultState<ArrayList<ClassifyResponse>>> = MutableLiveData()

此时在getProjectTitleData()中我想先判断拿到 titleData中的ArrayList做一些操作,再决定是否继续调用网络请求。

但是目前被ResultState包装对象后,就拿不到resultState.data这个字段了。这个ResultState应该怎么写才能暴露出类似getData()这样的方法?

我看谷歌的文档
https://developer.android.google.cn/jetpack/docs/guide#addendum
似乎也是这样,感觉很不方便啊

HeadInterceptor 的bug

我正在将此项目改造成适用于我公司业务的项目,在此过程中发现在给HeadInterceptor 传递header时有些问题
image
如图所示,从登录界面到首界面 HeadInterceptor 内方法体被调用时 headers 参数始终为空

navigation-runtime依赖?

你的项目里
api 'androidx.navigation:navigation-runtime:2.3.0'
但是官方文档里使用的是
api "androidx.navigation:navigation-fragment-ktx:2.3.0"
api "androidx.navigation:navigation-ui-ktx:2.3.0"
这之间有什么区别吗

整个项目写的逻辑清晰,特别是navigation这块以前没用明白过,这里再次感谢作者。

有什么方法可以 代替 onresume吗?

目前使用的是修改过的navigation,理论不会触发重绘,但是也带来了新的问题,
A ---> B 再从B --->A 时,假如不考虑viewpager之类的情况

有什么好办法可以在A页面监听返回事件吗? 类似activity的onresume

大概就是某个页面需要返回时刷新一下

在重构?

什么时候可以重构完?准备开新项目了

navigation切换fragment时 快速点击可能会崩溃

me.hgj.jetpackmvvm.ext.NavigationExt 中 NavController.navigateAction方法建议改为以下代码:

fun NavController.navigateAction(resId: Int, bundle: Bundle? = null, interval: Long = 500) {
val currentTime = System.currentTimeMillis()
if (currentTime >= lastTapTime + interval) {
lastTapTime = currentTime
try {
navigate(resId, bundle)
} catch (ignore: Exception) {}
}
}

当 fragment 中 action 的 duration设置为 0 时,连续点击两个不同的跳转会导致如下崩溃:

java.lang.IllegalArgumentException: Navigation action/destination com.xxx.xxx:id/action_aFragment_to_bFragment cannot be found from the current destination Destination(com.xxx.xxx:id/cFragment) label=cFragment class=com.xxx.xxx.ui.fragment.cFragment

登录页面全屏问题是这么设置的?

我的里面点击任意一项都会跳转到登录页面,而登录页面也是一个fragment 窗口加载的,可是登录页面的是一个全屏的页面,这个全屏怎么设置的。

UnPeekLiveData的疑问

🐔哥
me.hgj.jetpackmvvm.callback.livedata.event.EventLiveData和me.hgj.jetpackmvvm.callback.livedata.UnPeekLiveData有啥区别呀?为啥感觉都是防止旧数据倒灌的情况?

fragment切换时有卡顿

fragment用懒加载,切换动画还没执行完毕时数据就已经加载好了,这时页面会有渲染卡顿,有什么好办法解决吗?暂时用postDelayed 500 可以解决

是修改了Navigation使它支持Fragment复用吗?

原版的Navigation我知道会每次都销毁View。很蛋疼

那么框架内的FragmentNavigator 就是重写了replace的逻辑,变成了show和hide的吧

里面是否有用到反射?我担心如果用了反射以后谷歌一刀切不允许反射了出问题

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.