Code Monkey home page Code Monkey logo

mvvmlin's Introduction

MVVMLin

一个基于MVVM用Kotlin+Retrofit+协程+Databinding(ViewBinding)+LiveData来封装的快速开发框架: 项目地址:MVVMLin

框架简介

  • 使用技术 基于MVVM模式用了 kotlin+协程+retrofit+livedata+DataBinding
  • 基本封装 封装了BaseActivity、BaseFragment、BaseViewModel基于协和的网络请方式更加方便,考虑到有些小伙伴不太喜欢用DataBinding在xml中绑定数据的方式,也提供了相应的适配,两种方式自行选择。Retrofit2.6及以上版本提供了对协程的支持,使用起来更加方便. 增加了 Flow 的转换
  • 引入第三方库

AndroidUtilCode:包含了大量的常用工具类,简直是必备神器啊。

material-dialogs:弹窗

coil:图片加载(更适合KT的图片加载)

Retrofit:网络请求

使用方式

启用dataBinding

在主工程app的build.gradle的android {}中加入:

    buildFeatures {
        //dataBinding = true
        viewBinding = true
    }

依赖

在主项目app的build.gradle中依赖

dependencies {
    ...
   implementation 'com.github.AleynP:MVVMLin:2.0.0'
}

或者 下载到本地导入Module

配置 buildSrc (1.0.6 版本改为 butkdSrc 方式构建)

复制Demo的 buildSrc 到根目录,用Gradle 同步。AS会自动识别 buildSrc目录 (远程依赖可以忽略)

添加 FlowAdapter

    Retrofit.Builder()
    .addCallAdapterFactory(FlowAdapterFactory.create(true))
    //...
    .build()

如上添加 FlowAdapter后, Retrofit 可直接返回 Flow 类型。

快速开始

Activity

继承BaseVMActivity

class DetailActivity : 继承BaseVMActivity<NoViewModel, ViewBinding>() {

	override val layoutId() = R.layout.activity_detail

	override fun initView(savedInstanceState: Bundle?) {
       ....
    }

    override fun initData() {
      ....
    }
}

第一个泛型是ViewModel,如果页面很简单不需要ViewModel,可以继承BaseActivity。 第二个泛型是Databinding 或者 ViewBinding 的生成类,如果页面使用Databinding或者ViewBinding的话,就要传对应的Binding生成类,如果不使用DataBinding或者ViewBinding,传 ViewBinding 。基类不用初始化mBinding而会使用常规方式。 ** layoutId ** 方法返回对应布局。当使用ViewBinding时 不用重写此方法,其余都要重写 返回布局 Id initView()initData() 为默认实现,做初始化UI等操作

Fragment

继承BaseVMFragment

class HomeFragment : 继承BaseVMFragment<HomeViewModel, ViewBinding>() {

		override fun layoutId() = R.layout.home_fragment
		
		override fun initView(savedInstanceState: Bundle?) {  }
		
		override fun lazyLoadData() {
			....
		}
}

实现方法同Activity一样,Fragment多了懒加载方法lazyLoadData() 可选择性重写。

ViewModel

继承BaseViewModel

class HomeViewModel : BaseViewModel() {
		.........
}

在Application 中设置全局网络异常处理(可选)

MVVMLin.setNetException(CoroutineExceptionHandler { context, e ->
    //...
})

ViewModel 中所有网络请求都写要 BaseViewModel 的 launch 作用域中,如下:

Flow 方式(同 RxJava 相似)

// Service 用 Flow 接收
@GET("xxx/xxx")
fun getBannerData(): Flow<BaseResult<XXX>>>
class HomeViewModel : BaseViewModel() {
    private val homeRepository by lazy { InjectorUtil.getHomeRepository() }
    private val _banners = MutableSharedFlow<List<BannerBean>>()
    val mBanners: SharedFlow<List<BannerBean>> = _banners
    fun getBanner(refresh: Boolean = false) {
        //只返回结果,其他全抛自定义异常
        launch {
            homeRepository.getBannerData(refresh)
                .asResponse()
                .bindLoading(this@HomeViewModel)//绑定Lodaing
                .collect(_banners)
        }
    }
}
操作符

以下几个是用 Flow 时用到的操作符:

  • asResponse: 只取成功结果其他全抛异常
  • asSuccess:只做成功处理,不关心结果
  • bindLoading: 绑定Loading
  • netCache: 自定义错误处理,返回的是 ResponseThrowable

普通方式(不使用Flow)

注意不使用Flow时, Service 返回值直接用基类,并添加上 suspend

@GET("xxx/xxx")
suspend fun getBannerData(): BaseResult<XXX>
class ProjectViewModel : BaseViewModel() {
    fun getProjectList(cid: Int) {
        launch {
            homeRepository.getProjectList(page, cid).getOrThrow()
            .let {
                items.clear()
                items.addAll(it.datas)
            }
        }
    }
}
转换符

以下几个是不使用 Flow 时用到的转换符:

  • getOrThrow: 只取成功结果其他全抛异常
  • check:检测是否成功

IBaseResponse

由于请求中依赖了数据基类,我们每个项目的基类字段都不相同,所以我们根据后台的字段定义完基类以后,要实现IBaseResponde接口,如下:

data class BaseResult<T>(
    val errorMsg: String,
    val errorCode: Int,
    val data: T
) : IBaseResponse<T> {

    override fun code() = errorCode

    override fun msg() = errorMsg

    override fun data() = data

    override fun isSuccess() = errorCode == 0
}

来保证过滤请求结果的正常使用

例子

Demo中只展示了三种列表使用方式

不使用Databinging,结合BRVAH

详见Demo的 HomeFragment

使用Databinging,结合bindingcollectionadapter

结合bindingcollectionadapter不用写Adapter适配器了,详见Demo的 ProjectFragment

使用Databinging,结合BRVAH

BRVAH 对DataBinding也做了支持,详见Demo的 ** MeFragment**

最后

QQ群:(791382057)

mvvmlin's People

Contributors

aleyn97 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

mvvmlin's Issues

学习

小哥哥
有个小问题 就是 你home fragment 请求网络数据的时候 触发事件是 SwipeRefreshLayout setOnRefreshListener 就有下拉显示效果了 然后呢正常情况下 livedata 回来会把SwipeRefreshLayout的效果关掉 但是异常情况 并没有

最近用 jetpack+kotlin 替换 之前的 rxjava2等基础框架项目
也尝试着封装一个 jetpack+kotlin快速开发基类框架 在大量寻找和借鉴

有个小问题哈 就是 网络请求 一般情况下基类属性为{ code,msg,T} 就是请求到数据后 code不是正常返回结果 自己处理过滤抛一个异常 优雅不? 我之前在也是这样做的 在okhttp 搞一个拦截器 做了同样的事情

双击导航栏,请求数据,偶尔出现

2020-09-09 16:35:30.495 9965-9965/com.pcl.mvvm E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.pcl.mvvm, PID: 9965
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.next(ArrayList.java:860)
at com.aleyn.mvvm.binding.TabLayoutAdapter.setTabText(TabLayoutAdapter.kt:29)
at com.pcl.mvvm.databinding.ProjectFragmentBindingImpl.executeBindings(ProjectFragmentBindingImpl.java:162)
at androidx.databinding.ViewDataBinding.executeBindingsInternal(ViewDataBinding.java:473)
at androidx.databinding.ViewDataBinding.executePendingBindings(ViewDataBinding.java:445)
at androidx.databinding.ViewDataBinding$7.run(ViewDataBinding.java:197)
at androidx.databinding.ViewDataBinding$8.doFrame(ViewDataBinding.java:291)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:970)
at android.view.Choreographer.doCallbacks(Choreographer.java:796)
at android.view.Choreographer.doFrame(Choreographer.java:727)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

viewModel共享问题

在这个项目中,如果想让fragment共享activity的viewModel,该如何解决呢

开启混淆后crash

Caused by: java.lang.NoSuchMethodException: zy.inflate [class android.view.LayoutInflater]
at java.lang.Class.getMethod(Class.java:2072)
at java.lang.Class.getMethod(Class.java:1693)
at com.commonlib.base.BaseActivity$a.a(BaseActivity.kt:3)
at com.commonlib.base.BaseActivity$a.invoke(BaseActivity.kt:1)
at yj2.getValue(LazyJVM.kt:5)
at com.commonlib.base.BaseActivity.d(Unknown Source:2)
at com.commonlib.base.BaseActivity.h(BaseActivity.kt:1)
at com.commonlib.base.BaseActivity.onCreate(BaseActivity.kt:3)
at android.app.Activity.performCreate(Activity.java:8000)
at android.app.Activity.performCreate(Activity.java:7984)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3404)

问题

小哥哥 这个逻辑是不是有点小问题
image

BaseActivity中的写法限制了BaseActivity只能有儿子,不能有孙子~

class DetailActivity : MyBaseActivity()
abstract class MyBaseActivity : BaseActivity<NoViewModel, ViewDataBinding>() {
}

BaseActivity.kt:

private fun initViewDataBinding() {
	val cls =
		(javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[1] as Class<*>
	if (ViewDataBinding::class.java != cls && ViewDataBinding::class.java.isAssignableFrom(cls)) {
		mBinding = DataBindingUtil.setContentView(this, layoutId())
		mBinding?.lifecycleOwner = this
	} else setContentView(layoutId())
	createViewModel()
}

异常:

Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
        at com.aleyn.mvvm.base.BaseActivity.initViewDataBinding(BaseActivity.kt:49)
        at com.aleyn.mvvm.base.BaseActivity.onCreate(BaseActivity.kt:31)
        at android.app.Activity.performCreate(Activity.java:7383)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1218)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3256)

使用launchOnlyresult闪退

    launchGo({
        val result = homeRepository.login(map)
        if (!result.isSuccess()) {
            ToastUtils.showShort("" + result.message)
        }
    })

    launchOnlyresult({ homeRepository.login(map) }, {

    }, {
        // 这里是Error 返回   ()
    })

launchOnlyresult闪退 但是launchGo就是正常的

感谢

鄙人看过好多的mvvm,jetpack组件,作者大大应该是借鉴了好多开源框架,整合了其中优秀**,组装了这个快速开发框架,我也组装了一个,有些地方没并有作者的优雅,这个对我也有了一定的启发,感谢作者,为作者的开源精神点赞,建议加入 常用的扩展及baseactivity页面加入titlebar的控制

Caused by: java.lang.IllegalArgumentException: Type without superclass: module-info

如题:系统版本htc_5.0.2 这个问题
运行提示
The device might have stale dexed jars that don't match the current version (dexopt error).
gradle.properties 增加
android.enableJetifier=true android.enableD8.desugaring=false
之后
运行编译报错
Error while running desugar java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.android.build.gradle.internal.tasks.DesugarWorkerItem$DesugarAction.run(DesugarWorkerItem.java:107) at com.android.build.gradle.internal.tasks.Workers$ActionFacade.run(Workers.kt:348) at org.gradle.workers.internal.AdapterWorkAction.execute(AdapterWorkAction.java:50) at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:47) at org.gradle.workers.internal.AbstractClassLoaderWorker$1.create(AbstractClassLoaderWorker.java:46) at org.gradle.workers.internal.AbstractClassLoaderWorker$1.create(AbstractClassLoaderWorker.java:36) at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:98) at org.gradle.workers.internal.AbstractClassLoaderWorker.executeInClassLoader(AbstractClassLoaderWorker.java:36) at org.gradle.workers.internal.IsolatedClassloaderWorker.execute(IsolatedClassloaderWorker.java:54) at org.gradle.workers.internal.WorkerDaemonServer.execute(WorkerDaemonServer.java:56) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.process.internal.worker.request.WorkerAction.run(WorkerAction.java:118) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182) at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164) at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:412) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64) at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.IllegalArgumentException: Type without superclass: module-info at com.google.common.base.Preconditions.checkArgument(Preconditions.java:191) at com.google.devtools.build.android.desugar.DefaultMethodClassFixer.visit(DefaultMethodClassFixer.java:87) at org.objectweb.asm.ClassVisitor.visit(ClassVisitor.java:113) at com.google.devtools.build.android.desugar.InterfaceDesugaring.visit(InterfaceDesugaring.java:106) at org.objectweb.asm.ClassReader.accept(ClassReader.java:621) at org.objectweb.asm.ClassReader.accept(ClassReader.java:500) at com.google.devtools.build.android.desugar.Desugar.desugarClassesInInput(Desugar.java:553) at com.google.devtools.build.android.desugar.Desugar.desugarOneInput(Desugar.java:431) at com.google.devtools.build.android.desugar.Desugar.desugar(Desugar.java:373) at com.google.devtools.build.android.desugar.Desugar.main(Desugar.java:862) ... 34 more
bug.txt

模拟器可以运行到手机上提示报错

手机上运行报错。
`01/28 14:29:00: Launching 'app' on HTC HTC E9pw.
Installation did not succeed.
The application could not be installed: INSTALL_FAILED_DEXOPT

List of apks:
[0] 'D:\asProject\MVVMLin\app\build\outputs\apk\debug\app-debug.apk'
The device might have stale dexed jars that don't match the current version (dexopt error).`

build 过程中提示
ANTLR Tool version 4.5.3 used for code generation does not match the current runtime version 4.7.1ANTLR Runtime version 4.5.3 used for parser compilation does not match the current runtime version 4.7.1ANTLR Tool version 4.5.3 used for code generation does not match the current runtime version 4.7.1ANTLR Runtime version 4.5.3 used for parser compilation does not match the current runtime version 4.7.1[WARN] Incremental annotation processing requested, but support is disabled because the following processors are not incremental: androidx.room.RoomProcessor (DYNAMIC).

111111

about version update

as 4.0.2 build
`// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply from: "config.gradle"
buildscript {
ext.kotlin_version = "1.3.72"
repositories {
google()
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// classpath 'com.novoda:bintray-release:0.9.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
tasks.withType(Javadoc) {
options {
encoding "UTF-8"
charSet 'UTF-8'
links "http://docs.oracle.com/javase/7/docs/api"
}
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}`

Operating normally


as 4.1 build
`// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply from: "config.gradle"
buildscript {
ext.kotlin_version = "1.4.10"
repositories {
google()
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// classpath 'com.novoda:bintray-release:0.9.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
tasks.withType(Javadoc) {
options {
encoding "UTF-8"
charSet 'UTF-8'
links "http://docs.oracle.com/javase/7/docs/api"
}
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}`

Run prompt
10-19 11:14:49.739 19925-19925/com.pcl.mvvm E/AndroidRuntime: FATAL EXCEPTION: main Process: com.pcl.mvvm, PID: 19925 java.lang.RuntimeException: Unable to get provider androidx.lifecycle.ProcessLifecycleOwnerInitializer: java.lang.ClassNotFoundException: Didn't find class "androidx.lifecycle.ProcessLifecycleOwnerInitializer" on path: DexPathList[[zip file "/data/app/com.pcl.mvvm-1/base.apk"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64]] at android.app.ActivityThread.installProvider(ActivityThread.java:5555) at android.app.ActivityThread.installContentProviders(ActivityThread.java:5124) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5064) at android.app.ActivityThread.access$1500(ActivityThread.java:162) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1503) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:209) at android.app.ActivityThread.main(ActivityThread.java:5900) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1005) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:800) Caused by: java.lang.ClassNotFoundException: Didn't find class "androidx.lifecycle.ProcessLifecycleOwnerInitializer" on path: DexPathList[[zip file "/data/app/com.pcl.mvvm-1/base.apk"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64]] at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) at java.lang.ClassLoader.loadClass(ClassLoader.java:511) at java.lang.ClassLoader.loadClass(ClassLoader.java:469) at android.app.ActivityThread.installProvider(ActivityThread.java:5540) at android.app.ActivityThread.installContentProviders(ActivityThread.java:5124)  at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5064)  at android.app.ActivityThread.access$1500(ActivityThread.java:162)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1503)  at android.os.Handler.dispatchMessage(Handler.java:106)  at android.os.Looper.loop(Looper.java:209)  at android.app.ActivityThread.main(ActivityThread.java:5900)  at java.lang.reflect.Method.invoke(Native Method)  at java.lang.reflect.Method.invoke(Method.java:372)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1005)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:800)  Suppressed: java.lang.ClassNotFoundException: androidx.lifecycle.ProcessLifecycleOwnerInitializer at java.lang.Class.classForName(Native Method) at java.lang.BootClassLoader.findClass(ClassLoader.java:781) at java.lang.BootClassLoader.loadClass(ClassLoader.java:841) at java.lang.ClassLoader.loadClass(ClassLoader.java:504) ... 13 more Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available

phone v htc 5.0+

升级gradle后room报错

如题所示:
我将kotlin-gradle-plugin升级到1.6.10
gradle-wrapper.properties 升级到gradle-6.5-all
com.android.tools.build:gradle 升级到4.1.2

运行项目room报错,耗时很久没能解决,还望指点,谢谢!错误如下:
The query returns some columns [curPage, offset, over, pageCount, size, total, datas] which are not used by java.lang.Object. You can use @ColumnInfo annotation on the fields to specify the mapping. You can annotate the method with @RewriteQueriesToDropUnusedColumns to direct Room to rewrite your query to avoid fetching unused columns. You can suppress this warning by annotating the method with @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH). Columns returned by the query: curPage, offset, over, pageCount, size, total, datas. Fields in java.lang.Object: .
public abstract java.lang.Object getHomeList(int page, @org.jetbrains.annotations.NotNull()

微信截图_20220302175022

LiveData.observe()中出现异常无法继续接收数据的问题

博主,使用你的封装方法后出现了如下问题:

viewmodel

main_view_model

mian_activity

在触发Exception之后程序并没有崩溃,这个Exception走到了BaseViewModel#handleException的catch中,但是后面再去setValue时,ui就收不到通知了

LiveData

调试发现后面这个mDispatchingValue一直为true,博主知道怎么解决嘛?

网络解析问题

错误时间返回
图片
正确时间返回
图片
data 里边类型不一样,报解析失败,这个能跳过吗,只在成功的时间解析返回data

Module接入 MVVMLin 的一些注意

因为要对 BaseActivity等内部增加一些东西,所以我选择了以 module 的方式。按照说明,导入后->复制config.gradle文件->增加apply->依赖。 但是依然报错,Plugin with id 'com.novoda.bintray-release' not found 需要把 这行去掉。同时下方的 publish 的任务也去掉。

fragment replace 后livedata重复接收数据问题

您好,很感谢你的库,让我学到了很多东西,但是再使用fragment时候发现replace (共享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.