GithubHelp home page GithubHelp logo

zskingking / jetpack-mvvm Goto Github PK

View Code? Open in Web Editor NEW
1.3K 11.0 183.0 3.28 MB

使用Jetpack全家桶+Kotlin实现的Android社区App加音乐播放器。不写晦涩难懂的代码,尽量标清每一行注释,严格遵守六大基本原则,大量运用设计模式,此项目可快速帮你入手Kotlin、Jetpack。如果觉得对你有帮助,右上角点个star,事先谢过🍉🍉🍉

Kotlin 68.33% Java 31.67%

jetpack-mvvm's Introduction

注意注意

as升级到4.2后jdk location默认是11,而本项目jdk 1.8所以有冲突,会报java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException错误。具体解决方案 https://stackoverflow.com/questions/67410927/java-lang-noclassdeffounderror-javax-xml-bind-jaxbexception-after-updating-to-a

建议结合本人两篇关于架构的文章去理解项目

引入Jetpack架构后,你的App会发生哪些变化?

关于Android架构,你是否还在生搬硬套?

1. 背景

为了更深入的理解Jetpack中各个组件,在前段时间基于Jetpack MVVM实现了一版 WanAndroid。相比上一版的MVP增加了夜间模式音乐播放器,播放器界面仿照网易云音乐App中也大量的使用属性动画让界面简约而不简陋。先上图look一波

2. 应用技术

基础框架选用MVVM,选用的Jetpack组件包括Lifecycle、ViewModel、LiveData、DataBinDing、Navigation、Room

项目基于Navigation由单ActivityFragment实现,使用这种模式给我最直观的感受就是,比如点击搜索进入搜索界面的衔接动画,在多Activity之间是不可能这么连贯的。

整个项目全部使用Kotlin语言,广泛应用了协程编写了大量的扩展函数

关于每个模块的职责我是这样定义的:

Model

对应项目中Repository,做数据请求以及业务逻辑。

ViewModel

基于Jetpack中的ViewModel进行封装(友情提示:Jetpack ViewModelMVVM ViewModel没有半毛钱关系,切勿将两个概念混淆)。在项目中VM层职责很简单,通过内部通过LiveData做数据存储,以及结合DataBinding做数据绑定。

View

尽量只做UI渲染。与MVP中不同,View是通过DataBinding与数据进行绑定,ActivityFragment非常轻盈只专注于生命周期的管理,数据渲染基本全部由DataBinding+BindAdapter实现。

关于MVVM模版类的封装可至package com.zs.base_library.base(包名)下查看。

网络层

关于网络层继续使用OkHttp Retrofit,并对Retrofit多ApiService以及多域名进行了封装。

数据库

项目中历史记录是在本地数据库进行维护的,关于数据库使用了Jetpack中的Room

主题切换

Android原生提供的夜间切换好像又API版本限制,所以就没有用。我个人在本地维护了两套主题,可动态切换。当前包含白天、夜间两套主题

3. 关于注释

我个人是非常喜欢写注释的,基本每一个复杂的功能都有对应的文字描述

项目中运用了大量的设计模式,每用到一种设计模式我都会结合当时场景进行解释,比如播放器中某个接口,我会这样写注释:


/**
 * des 所有的具体Player必须实现该接口,目的是为了让PlayManager不依赖任何
 *     具体的音频播放实现,原因大概有两点
 *
 *     1.PlayManager包含业务信息,Player不应该与业务信息进行耦合,否则每次改动都会对业务造成影响
 *
 *     2.符合开闭原则,如果需要对Player进行替换势必会牵连到PlayManager中的业务,因而造成不必要的麻烦
 *       如果基于IPlayer接口编程,扩展出一个Player即可,正所谓对扩展开放、修改关闭
 *
 * @author zs
 * @date 2020-06-23
 */
interface IPlayer {
    ....
    ....
}

/**
 * des 音频管理
 *     通过单例模式实现,托管音频状态与信息,并且作为唯一的可信源
 *     通过观察者模式统一对状态进行分发
 *     实则是一个代理,将目标对象Player与调用者隔离,并且在内部实现了对观察者的注册与通知
 * @author zs
 * @date 2020/6/25
 */
class PlayerManager private constructor() : IPlayerStatus {
     ....
     ....
}

写在最后

此项目中你很难看到不明不白的代码。JetpackKotlin是大势所趋,既然拒绝不了那何不开心的拥抱。功能目前已完成90%,代码也在持续优化,欢迎大家关注、下载源代码,让我们共同学习、共同进步。

jetpack-mvvm's People

Contributors

zskingking 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

jetpack-mvvm's Issues

项目请求数据报错

2021-05-14 15:06:59.177 15290-15290/com.zs.zs_jetpack W/System.err: java.net.SocketTimeoutException: failed to connect to www.wanandroid.com/47.104.74.169 (port 443) from /192.168.17.44 (port 46810) after 10000ms
2021-05-14 15:06:59.177 15290-15290/com.zs.zs_jetpack W/System.err: at libcore.io.IoBridge.connectErrno(IoBridge.java:185)
2021-05-14 15:06:59.178 15290-15290/com.zs.zs_jetpack W/System.err: at libcore.io.IoBridge.connect(IoBridge.java:129)
2021-05-14 15:06:59.178 15290-15290/com.zs.zs_jetpack W/System.err: at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:137)
2021-05-14 15:06:59.178 15290-15290/com.zs.zs_jetpack W/System.err: at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:391)
2021-05-14 15:06:59.178 15290-15290/com.zs.zs_jetpack W/System.err: at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:231)
2021-05-14 15:06:59.178 15290-15290/com.zs.zs_jetpack W/System.err: at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:213)
2021-05-14 15:06:59.179 15290-15290/com.zs.zs_jetpack W/System.err: at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
2021-05-14 15:06:59.179 15290-15290/com.zs.zs_jetpack W/System.err: at java.net.Socket.connect(Socket.java:621)
2021-05-14 15:06:59.179 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.platform.AndroidPlatform.connectSocket(AndroidPlatform.kt:63)
2021-05-14 15:06:59.179 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.kt:295)
2021-05-14 15:06:59.179 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:207)
2021-05-14 15:06:59.179 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
2021-05-14 15:06:59.179 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
2021-05-14 15:06:59.180 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
2021-05-14 15:06:59.180 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
2021-05-14 15:06:59.180 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
2021-05-14 15:06:59.180 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2021-05-14 15:06:59.180 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
2021-05-14 15:06:59.180 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2021-05-14 15:06:59.181 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
2021-05-14 15:06:59.181 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2021-05-14 15:06:59.181 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
2021-05-14 15:06:59.181 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2021-05-14 15:06:59.181 15290-15290/com.zs.zs_jetpack W/System.err: at com.zs.base_library.http.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:75)
2021-05-14 15:06:59.181 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2021-05-14 15:06:59.182 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
2021-05-14 15:06:59.182 15290-15290/com.zs.zs_jetpack W/System.err: at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:517)
2021-05-14 15:06:59.182 15290-15290/com.zs.zs_jetpack W/System.err: at java.util.concurrent.ThreadPoolExecutor.processTask(ThreadPoolExecutor.java:1187)
2021-05-14 15:06:59.182 15290-15290/com.zs.zs_jetpack W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152)
2021-05-14 15:06:59.182 15290-15290/com.zs.zs_jetpack W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
2021-05-14 15:06:59.182 15290-15290/com.zs.zs_jetpack W/System.err: at java.lang.Thread.run(Thread.java:784)

通过buildSrc统一管理依赖库

请教一下,你于2020年9月17号添加的“buildSrc”是个什么模块?怎么与“app”模块和“base-library”模块产生联系的,怎么在app和base-library中就能直接调用 buildSrc中的那几个objec类了?我看了半天,没有搞懂,烦请兄弟有空帮忙释疑一下,感谢。 ps:代码写的的确很美观

调用nav().navigateUp的问题

页面调用nav().navigateUp返回,之后再次打开此页面的时候observe,中的LiveData监听都产生了一次回调

编译报错

image
这个地方没有viewModel能编译成dataBindingImpl吗

自定义颜色引用报错

我想把项目重新写一下 然后splash 中 android:background="?attr/main_bg_1" 的颜色引用 报错 Failed to resolve attribute at index 13: TypedValue{t=0x2/d=0x7f0301da a=-1} 主题和自定义颜色也复制到新项目了 �请问大神是什么原因

build错误 Execution failed for task ':zsLib:compileDebugJavaWithJavac'.

系统版本:macOS 11.5.2
AS版本:Android Studio Flamingo | 2022.2.1 Patch 2

编译爆如下错误:

* What went wrong:
Execution failed for task ':zsLib:compileDebugJavaWithJavac'.
> Failed to calculate the value of task ':zsLib:compileDebugJavaWithJavac' property 'options.generatedSourceOutputDirectory'.
   > Querying the mapped value of map(java.io.File property(org.gradle.api.file.Directory, fixed(class org.gradle.api.internal.file.DefaultFilePropertyFactory$FixedDirectory, /Users/zxkang/WorkSpace/Java/Jetpack-Mvvm/zsLib/build/generated/ap_generated_sources/debug/out)) org.gradle.api.internal.file.DefaultFilePropertyFactory$ToFileTransformer@66a3a6b5) before task ':zsLib:compileDebugJavaWithJavac' has completed is not supported

关于框架的一些疑虑

谢谢大佬的框架,我在挑选框架的时候看到了大佬的库,感觉很不错。不过其中有一些小疑虑。

1、就是databinding与业务的紧密耦合,导致页面的复用性很差,大佬可有想过用其他方式去实现。
2、我看一个UI组件(fragment,activity)中只能使用一个viewModel与页面的databinding 通过DataBindingConfig绑定,如果一个fragment或者actvity中有多个业务的组合,即可能有多个viewmodel同时作为一个UI单元的数据源时,框架该如何做?

最后再次谢谢大佬的框架。

对getInternal的引用不明确

编译的时候,出现下面的错误:

Jetpack-Mvvm/app/build/generated/source/kapt/debug/com/zs/zs_jetpack/databinding/FragmentMineBindingImpl.java:193: 错误: 对getInternal的引用不明确
                        vmInternal = vm.getInternal();
                                       ^
  MineVM 中的方法 getInternal() 和 MineVM 中的方法 getInternal() 都匹配

请问该怎么解决呢?

关于BaseRepo和BaseViewModel中launch函数的封装

首先赞一下大佬掘金的两篇高质量文章。
看了下代码,对launch{}这个封装 有几个小建议:
一是 Dispatcher建议手动传入,这样使用者更明确block: suspend () -> T的执行环境
二是 success和error这两个callback的线程环境建议统一下,比如要么与block: suspend () -> T 相同,要么统一切换到主线程。
三是

onFailure {
                it.printStackTrace()
                getApiException(it).apply {
                    error?.invoke(this)
                    toast(errorMessage)
                    //统一响应错误信息
                    errorLiveData.value = this
                }
            }

这里 toast(errorMessage) errorLiveData.value = this 可能有bug哈 建议用withContext(Dispatchers.Main.immediate) 包一下

关于LiveData状态共享的倒灌问题

关于LiveData状态共享的倒灌问题
请问
一个LiveData被多个fragment分享,当前一个fragment收到后退出,再返回,仍然会收到LiveData之前的值,而理想的状态是Fragment只接收到一次,销耗后就不再接受旧值

Adapter item 获取自定义属性

您好,为什么adapter中item布局使用textview自定义属性style="@style/text_2"(?attr/theme_color_2)直接回崩溃掉,不在recycleview里使用就会正常呢

Demo 无法运行

Build file 'E:..\Jetpack-Mvvm\app\build.gradle' line: 7

A problem occurred evaluating project ':app'.

Could not get unknown property 'Version' for object of type com.android.build.gradle.internal.dsl.BaseAppModuleExtension.

处理token过期返回登录

你好:
正好最近在看jetpack相关的,你写的这个例子很不错,
想请教下,如何处理token过期呢? 每个接口都可能返回token过期的信息,如果token过期返回登录页面,这个问题在哪处理比较好呢?
我看你封装了统一的错误处理,如果在这里面去跳转到登录总感觉不是太好。

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.