Giter Site home page Giter Site logo

fashare2015 / mvvm-juejin Goto Github PK

View Code? Open in Web Editor NEW
397.0 13.0 57.0 6.01 MB

高仿"掘金Android App": databinding + kotlin + rx 的优雅实践。(持续打磨中~)

License: MIT License

Java 48.17% Kotlin 38.78% CSS 11.13% JavaScript 0.53% HTML 0.30% Shell 1.08%
databinding kotlin mvvm android juejin rx retrofit okhttp

mvvm-juejin's Introduction

高仿掘金App —— 基于 databinding

1. 项目初衷

不同于前端 vue、 react 的火热, 移动端的 databinding 好像不受待见。鉴于 vue、 react 都有各自成熟的生态圈,我希望通过这个项目打磨出一个简单易用的 databinding 组件库

1.1 data -> view,舍弃 Adapter

之前有不少前辈专门针对 RecyclerView 做了各自的封装,完全省去了 Adapter, 比如:

1.2 更进一步:view -> data -> view

在本项目中,你将会看到一个带有 下拉刷新 + 上拉加载 的页面如何简化到10+行java代码 ! see NotifyVM.kt

2. 模块概览

接口全抓自掘金app, 支持登录、注册(走的官方接口,并非假数据哦~)

  • 已完成:
    • 登录、注册:可以用自己的掘金帐号登录,或者临时注册一个
    • 首页:热门推荐及文章列表,以及各个分类页面(Android、前端、产品。。。)
    • 发现:一级页面,包括 banner、活动、沸点、热门文章
    • 消息:完成消息列表
    • 我的:一级页面,包括登录与未登录两个状态
    • 文章详情页面: 文章 html 以及 下方的评论列表
  • TODO:
    • splash 页
    • 第三方登录
    • 发现页 - 搜索模块、活动、沸点的二级页面
    • 我的 - 个人信息页,包括从用户头像跳转
    • 我的 - 喜欢、收藏、设置等二级页面
    • 发布文章页
    • 收藏、评论、分享等其他功能
    • 夜间模式
    • ...

3. 效果图

首页 文章详情

登录 其他

4. 技术栈

  • databinding
  • kotlin
  • rxJava + rxAndroid
  • retrofit + okhttp
  • glide

5. 关于 "10+行" 实现的分页列表

我们来看第3个tab - 消息列表: see NotifyVM.kt

消息

// NotifyListVM.kt
@ResHolder(R.layout.item_notify_list)                               // item 布局
@HeaderResHolder(R.layout.header_notify)                            // header 布局
class NotifyListVM : TwoWayListVM<NotifyBean>() {
    override val loadTask = { lastItem: NotifyBean? ->              // 网络请求(refresh、loadMore 二合一)
        ApiFactory.getApi(JueJinApis.Notify:: class.java)
            .getUserNotification(lastItem?.createdAtString?: "")
            .compose(Composers.handleError())
    }
    override val onItemClick = ArticleActivity.START_FROM_NOTIFY    // 点击事件
    override val headerData = Any()
}

框架中封装了TwoWayListVM,我们的NotifyListVM继承与它,并在布局中与RecyclerView绑定在一起。 重点来了:

  1. view(pullToRefresh) -> data(list): 当view有动作(下拉刷新 or 上拉加载),框架会自行调用loadTask,然后更新TwoWayListVM.data
  2. data(list) -> view(RecyclerView): 而当TwoWayListVM.data发生变化,会自动触发RecyclerView刷新。

然后,配合 kotlin 简洁的语法,我们实现了也许是史上最简洁???的分页列表。

6. 项目持续打磨中,有兴趣给个star~

7. 参考

Android DataBinding 数据绑定 —— QQ音乐技术团队

官方文档

完全掌握Android Data Binding

MVVMLight

mvvm-juejin's People

Contributors

fashare2015 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

mvvm-juejin's Issues

编译不了

Error:Execution failed for task ':base-ui:compileReleaseKotlin'.

Compilation error. See log for more details

MalformedByteSequenceException:Windows下xml中的汉字导致编译不过

Error:com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: 3 字节的 UTF-8 序列的字节 3 无效。
Error:java.lang.RuntimeException: failure, see logs for details.
Error:com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: 3 字节的 UTF-8 序列的字节 3 无效。
Error:Execution failed for task ':app:kaptDebugKotlin'.

Internal compiler error. See log for more details

关于在VM中保留View引用的问题

Hi 留意到VM的部分实现,如ArticleVM 中保存了对view (如RecyclerView)的引用。
个人认为如果想要达成更好的复用, ViewModel中可以除去对View的直接引用吧。
不知在当前代码的实现层面是否有别的考虑?

更多对于MVVM的讨论 可以参考这里.

3.0不推荐用compile了

compile改成implementation,比如如下

implementation "com.github.bumptech.glide:glide:$glideVersion"
kapt "com.github.bumptech.glide:compiler:$glideVersion"
implementation "com.github.bumptech.glide:okhttp3-integration:$glideVersion"
implementation ("com.github.bumptech.glide:recyclerview-integration:$glideVersion@aar") {
    // Excludes the support library because it's already included by Glide.
    transitive = false
}

debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
implementation 'org.sufficientlysecure:html-textview:3.4'

运行到手机上出错

Error:java.lang.RuntimeException: failure, see logs for details.
Error:com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: 3 字节的 UTF-8 序列的字节 3 无效。
Error:Execution failed for task ':app:kaptDebugKotlin'.

Internal compiler error. See log for more details

TwoWayListVM里面这样的addAll不会很费时间和内存吗?

open val loadTaskObserver : ((List<T>, Refreshable?) -> Observer<List<T>>)? = { originData: List<T>, refreshable: Refreshable? ->
        object: Observer<List<T>>{
            override fun onNext(netData: List<T>) {
                val lastItem = if(!originData.isEmpty()) originData[originData.size-1] else null
                val isLoadMore = lastItem != null

                val newData = ArrayList<T>()
                if (isLoadMore) {
                    newData.addAll(originData)
                }
                newData.addAll(netData)

                data.clear()
                data.addAll(newData)
            }

            override fun onComplete() {
                refreshable?.endRefresh()
            }

            override fun onError(e: Throwable) {}

            override fun onSubscribe(d: Disposable) {}
        }
    }

TwoWayListVM里面加载数据是每次都把原数据复制一次,随着数据的加载,originData肯定是越来越大的,每次都把它复制一遍不会很费时间和内存吗?尤其是它变得越来越大的时候,虽然整个过程是用RxJava做了异步的

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.