JetPackMvvm 一个Jetpack结合MVVM的快速开发框架,基于MVVM模式集成谷歌官方推荐的JetPack组件库:LiveData、ViewModel、Lifecycle、Navigation组件

Overview

Platform GitHub license GitHub license

🐔 🐔 🐔 JetPackMvvm

  • 基于MVVM模式集成谷歌官方推荐的JetPack组件库:LiveData、ViewModel、Lifecycle、Navigation组件
  • 使用kotlin语言,添加大量拓展函数,简化代码
  • 加入Retrofit网络请求,协程,帮你简化各种操作,让你快速请求网络

演示Demo

已用该库重构了我之前的玩安卓项目,利用Navigation组件以单Activity+Fragment架构编写,优化了很多代码,对比之前的mvp项目,开发效率与舒适度要提高了不少,想看之前MVP的项目可以去 https://github.com/hegaojian/WanAndroid

效果图展示

项目效果图

APK下载:

1.如何集成

  • 1.1 在root's build.gradle中加入Jitpack仓库
allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
  • 1.2 在app's build.gradle中添加依赖
dependencies {
  ...
  implementation 'com.github.hegaojian:JetpackMvvm:1.2.5'
}
  • 1.3 在app's build.gradle中,android 模块下开启DataBinding(如果你不想用DataBinding,请忽略这一步)
AndroidStudio 4.0 以下版本------>
android {
    ...
    dataBinding {
        enabled = true 
    }
}

AndroidStudio 4.0及以上版本 ------>
android {
    ...
   buildFeatures {
        dataBinding = true
    }
}
 

2.继承基类

一般我们项目中都会有一套自己定义的符合业务需求的基类 BaseActivity/BaseFragment,所以我们的基类需要继承本框架的Base类

  • 不想用Databinding的-------可以继承 BaseVmActivity/BaseVmFragment
  • 用Databinding的-----------可以继承BaseVmDbActivity/BaseVmDbFragment**

Activity:

abstract class BaseActivity<VM : BaseViewModel, DB : ViewDataBinding> : BaseVmDbActivity<VM, DB>() {
     /**
     * 当前Activity绑定的视图布局Id abstract修饰供子类实现
     */
    abstract override fun layoutId(): Int
    /**
     * 当前Activityc创建后调用的方法 abstract修饰供子类实现
     */
    abstract override fun initView(savedInstanceState: Bundle?)

    /**
     * 创建liveData数据观察
     */
    override override fun createObserver()


    /**
     * 打开等待框 在这里实现你的等待框展示
     */
    override fun showLoading(message: String) {
       ...
    }

    /**
     * 关闭等待框 在这里实现你的等待框关闭
     */
    override fun dismissLoading() {
       ...
    }
}

Fragment:

abstract class BaseFragment<VM : BaseViewModel,DB:ViewDataBinding> : BaseVmDbFragment<VM,DB>() {
    /**
     * 当前Fragment绑定的视图布局Id abstract修饰供子类实现
     */
    abstract override fun layoutId(): Int
   
    abstract override fun initView(savedInstanceState: Bundle?)

    /**
     * 懒加载 只有当前fragment视图显示时才会触发该方法 abstract修饰供子类实现
     */
    abstract override fun lazyLoadData()

    /**
     * 创建liveData数据观察 懒加载之后才会触发
     */
    override override fun createObserver()
  
    /**
     * Fragment执行onViewCreated后触发的方法 
     */
    override fun initData() {

    }
    
   /**
     * 打开等待框 在这里实现你的等待框展示
     */
    override fun showLoading(message: String) {
       ...
    }

    /**
     * 关闭等待框 在这里实现你的等待框关闭
     */
    override fun dismissLoading() {
       ...
    }
}

3.编写一个登录功能

  • 3.1 编写fragment_login.xml界面后转换成 databind 布局(鼠标停在根布局,Alt+Enter 点击提示 Convert to data binding layout即可)
.... ">
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:bind="http://schemas.android.com/tools">
    <data>
       
    data>
    <LinearLayout>
       ....
    LinearLayout>
 layout>   
  • 3.2 创建LoginViewModel类继承BaseViewModel
class LoginViewModel : BaseViewModel() {
  
}
  • 3.3 创建LoginFragment 继承基类传入相关泛型,第一个泛型为你创建的LoginViewModel,第二个泛型为ViewDataBind,保存fragment_login.xml后databinding会生成一个FragmentLoginBinding类。(如果没有生成,试着点击Build->Clean Project)
class LoginFragment : BaseFragment<LoginViewModel, FragmentLoginBinding>() {
    
    /**
     *  当前fragment绑定的布局
     */
    override fun layoutId() = R.layout.fragment_login
    
    /**
     *  初始化操作
     */
    override fun initView(savedInstanceState: Bundle?) {
        ...
    }
    
    /**
     *  fragment 懒加载
     */
    override fun lazyLoadData() { 
        ...
    }
}

4.网络请求(Retrofit+协程)

  • 4.1 新建请求配置类继承 BaseNetworkApi 示例:
class NetworkApi : BaseNetworkApi() {

   companion object {
         
        val instance: NetworkApi by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { NetworkApi() }

        //双重校验锁式-单例 封装NetApiService 方便直接快速调用
        val service: ApiService by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            instance.getApi(ApiService::class.java, ApiService.SERVER_URL)
        }
    }
   
    /**
     * 实现重写父类的setHttpClientBuilder方法,
     * 在这里可以添加拦截器,可以对 OkHttpClient.Builder 做任意你想要做的骚操作
     */
    override fun setHttpClientBuilder(builder: OkHttpClient.Builder): OkHttpClient.Builder {
        builder.apply {
            //示例:添加公共heads,可以存放token,公共参数等, 注意要设置在日志拦截器之前,不然Log中会不显示head信息
            addInterceptor(MyHeadInterceptor())
            // 日志拦截器
            addInterceptor(LogInterceptor())
            //超时时间 连接、读、写
            connectTimeout(10, TimeUnit.SECONDS)
            readTimeout(5, TimeUnit.SECONDS)
            writeTimeout(5, TimeUnit.SECONDS)
        }
        return builder
    }

    /**
     * 实现重写父类的setRetrofitBuilder方法,
     * 在这里可以对Retrofit.Builder做任意骚操作,比如添加GSON解析器,protobuf等
     */
    override fun setRetrofitBuilder(builder: Retrofit.Builder): Retrofit.Builder {
        return builder.apply {
            addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
            addCallAdapterFactory(CoroutineCallAdapterFactory())
        }
    }
}
  • 4.2如果你请求服务器返回的数据有基类(没有可忽略这一步)例如:
{
    "data": ...,
    "errorCode": 0,
    "errorMsg": ""
}

该示例格式是 玩Android Api返回的数据格式,如果errorCode等于0 请求成功,否则请求失败 作为开发者的角度来说,我们主要是想得到脱壳数据-data,且不想每次都判断errorCode==0请求是否成功或失败 这时我们可以在服务器返回数据基类中继承BaseResponse,实现相关方法:

data class ApiResponse<T>(var errorCode: Int, var errorMsg: String, var data: T) : BaseResponse
   () {

    
   // 这里是示例,wanandroid 网站返回的 错误码为 0 就代表请求成功,请你根据自己的业务需求来编写
    
   override 
   fun 
   isSucces() 
   = errorCode 
   == 
   0

    
   override 
   fun 
   getResponseCode() 
   = errorCode

    
   override 
   fun 
   getResponseData() 
   = data

    
   override 
   fun 
   getResponseMsg() 
   = errorMsg

}
  
  • 4.3 在ViewModel中发起请求,所有请求都是在viewModelScope中启动,请求会发生在IO线程,最终回调在主线程上,当页面销毁的时候,请求会统一取消,不用担心内存泄露的风险,框架做了2种请求使用方式

1、将请求数据包装给ResultState,在Activity/Fragment中去监听ResultState拿到数据做处理

() { private val requestLoginRegisterViewModel: RequestLoginRegisterViewModel by viewModels() /** * 当前fragment绑定的布局 */ override fun layoutId() = R.layout.fragment_login /** * 初始化操作 */ override fun initView(savedInstanceState: Bundle?) { ... } /** * fragment 懒加载 */ override fun lazyLoadData() { ... } override fun createObserver(){ //脱壳 requestLoginRegisterViewModel.loginResult.observe(viewLifecycleOwner, Observer { resultState -> parseState(resultState, { //登录成功 打印用户 it.username.logd() }, { //登录失败(网络连接问题,服务器的结果码不正确...异常都会走在这里) showMessage(it.errorMsg) }) }) //不脱壳 requestLoginRegisterViewModel.loginResult2.observe(viewLifecycleOwner, Observer {resultState -> parseState(resultState,{ if(it.errorCode==0){ //登录成功 打印用户名 it.data.username.logd() }else{ //登录失败 showMessage(it.errorMsg) } },{ //请求发生了异常 showMessage(it.errorMsg) }) }) } } ">
class RequestLoginViewModel: BaseViewModel {

  //自动脱壳过滤处理请求结果,自动判断结果是否成功
    var loginResult = MutableLiveData<ResultState<UserInfo>>()
    
  //不用框架帮脱壳
    var loginResult2 = MutableLiveData<ResultState<ApiResponse<UserInfo>>>()
    
  fun login(username: String, password: String){
   //1.在 Activity/Fragment的监听回调中拿到已脱壳的数据(项目有基类的可以用)
        request(
            { HttpRequestCoroutine.login(username, password) }, //请求体
            loginResult,//请求的结果接收者,请求成功与否都会改变该值,在Activity或fragment中监听回调结果,具体可看loginActivity中的回调
            true,//是否显示等待框,,默认false不显示 可以默认不传
            "正在登录中..."//等待框内容,可以默认不填请求网络中...
        )
        
   //2.在Activity/Fragment中的监听拿到未脱壳的数据,你可以自己根据code做业务需求操作(项目没有基类的可以用)
        requestNoCheck(
          {HttpRequestCoroutine.login(username,password)},
          loginResult2,
          true,
          "正在登录中...") 
}


class LoginFragment : BaseFragment<LoginViewModel, FragmentLoginBinding>() {
    
    private val requestLoginRegisterViewModel: RequestLoginRegisterViewModel by viewModels()
    
    /**
     *  当前fragment绑定的布局
     */
    override fun layoutId() = R.layout.fragment_login
    
    /**
     *  初始化操作
     */
    override fun initView(savedInstanceState: Bundle?) {
        ...
    }
    
    /**
     *  fragment 懒加载
     */
    override fun lazyLoadData() { 
        ...
    }
    
    override fun createObserver(){
      //脱壳
       requestLoginRegisterViewModel.loginResult.observe(viewLifecycleOwner,
            Observer { resultState ->
                parseState(resultState, {
                    //登录成功 打印用户
                    it.username.logd()
                }, {
                    //登录失败(网络连接问题,服务器的结果码不正确...异常都会走在这里)
                    showMessage(it.errorMsg)
                })
            })
    
       //不脱壳
       requestLoginRegisterViewModel.loginResult2.observe(viewLifecycleOwner, Observer {resultState ->
               parseState(resultState,{
                   if(it.errorCode==0){
                       //登录成功 打印用户名
                       it.data.username.logd()
                   }else{
                       //登录失败
                       showMessage(it.errorMsg)
                   }
               },{
                   //请求发生了异常
                   showMessage(it.errorMsg)
               })
           })
   } 
}

2、 直接在当前ViewModel中拿到请求结果

class RequestLoginViewModel : BaseViewModel() {
    
  fun login(username: String, password: String){
   //1.拿到已脱壳的数据(项目有基类的可以用)
     request({HttpRequestCoroutine.login(username,password)},{
             //请求成功 已自动处理了 请求结果是否正常
             it.username.logd()
         },{
             //请求失败 网络异常,或者请求结果码错误都会回调在这里
             it.errorMsg.logd()
         },true,"正在登录中...")
        
   //2.拿到未脱壳的数据,你可以自己根据code做业务需求操作(项目没有基类或者不想框架帮忙脱壳的可以用)
       requestNoCheck({HttpRequestCoroutine.login(username,password)},{
            //请求成功 自己拿到数据做业务需求操作
            if(it.errorCode==0){
                //结果正确
                it.data.username.logd()
            }else{
                //结果错误
                it.errorMsg.logd()
            }
        },{
            //请求失败 网络异常回调在这里
            it.errorMsg.logd()
        },true,"正在登录中...")
}
 

注意:使用该请求方式时需要注意,如果该ViewModel并不是跟Activity/Fragment绑定的泛型ViewModel,而是

val mainViewModel:MainViewModel by viewModels() 或者 val mainViewModel:MainViewModel by activityViewModels() 获取的 如果请求时要弹出loading,你需要在Activity | Fragment中添加以下代码:

addLoadingObserve(viewModel)

4.4 开启打印日志开关

设置全局jetpackMvvmLog变量 是否打开请求日志,默认false不打印,如需要打印日志功能,请设值为 true

5.获取ViewModel

  • 5.1我们的activity/fragment会有多个ViewModel,按传统的写法感觉有点累
 val mainViewModel = ViewModelProvider(this,
            ViewModelProvider.AndroidViewModelFactory(application)).get(MainViewModel::class.java)

**现在官方Ktx有拓展函数可以轻松调用

//在activity中获取当前Activity级别作用域的ViewModel
 private val mainViewModel:MainViewModel by viewModels()
 
//在activity中获取Application级别作用域的ViewModel(注,这个是本框架提供的,Application类继承框架的BaseApp才有用)
 private val mainViewModel by lazy { getAppViewModel<MainViewModel>()}

//在fragment中获取当前Fragment级别作用域的ViewModel
 private val mainViewModel:MainViewModel by viewModels()

//在fragment中获取父类Activity级别作用域的ViewModel
private val mainViewModel:MainViewModel by activityViewModels()

//在fragment中获取Application级别作用域的ViewModel(注,这个是本框架提供的,Application类继承框架的BaseApp才有用)
private val mainViewModel by lazy { getAppViewModel<MainViewModel>()}

6.写了一些常用的拓展函数

 算了不写了,这个不重要,想具体看的话可以在
 me.hgj.jetpackmvvm.ext.util
 me.hgj.jetpackmvvm.ext.view
 的包中看,反正你也可以自己写,按照自己的喜好与需求来

7.混淆

-keep class me.hgj.jetpackmvvm.**{*;}
-keep class com.google.android.material.** {*;}
-keep class androidx.** {*;}
-keep public class * extends androidx.**
-keep interface androidx.** {*;}
-dontwarn com.google.android.material.**
-dontnote com.google.android.material.**
-dontwarn androidx.**

感谢

联系

  • QQ交流群:419581249

License

 Copyright 2019, hegaojian(何高建)       
  
   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.
Comments
  • viewpager2+Fragment 另外一个内存泄漏问题

    viewpager2+Fragment 另外一个内存泄漏问题

    作者你好,我最近也在使用ViewPager2 + Fragment,发现如果fragment比较多,然后offscreenPageLimit不设置的话,LeakCanary就会报内存泄漏。同样在demo中,如果把你们写的offscreenPageLimit注释掉,然后在多个fragment中来回切换,也会报内存泄漏。这个如果不设置offscreenPageLimit,不知道有没有什么其他好的解决方案

    opened by taichushouwang 10
  • navigation切换fragment时 快速点击可能会崩溃

    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

    opened by zhushenwudi 9
  • ResultState包装对象后,只能在observe拿到数据吗?

    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 似乎也是这样,感觉很不方便啊

    opened by ppg408331701 6
  • BaseVmDbActivity 和 BaseVmActivity 有重复的代码,为什么继承实现呢?

    BaseVmDbActivity 和 BaseVmActivity 有重复的代码,为什么继承实现呢?

    abstract class BaseVmDbActivity<VM : BaseViewModel, DB : ViewDataBinding> : BaseVmActivity() {

    lateinit var mDatabind: DB
    
    /**
     * 创建DataBinding
     */
    override fun createContentView() {
        mDatabind = DataBindingUtil.setContentView(this, layoutId())
        mDatabind.lifecycleOwner = this
    }
    

    }

    优化建议 
    opened by KevinChang007 5
  • 不知道算不算bug,parseState的loading回调不成功,

    不知道算不算bug,parseState的loading回调不成功,

    sueecss和error能打印出来,但是laoding打印不出来

                data.observe(viewLifecycleOwner, Observer {resultState->
                    parseState(resultState, {
                      
                        LogUtils.e("sueecss")
                    },{
                        LogUtils.e("error")
                    },{
                        LogUtils.e("laoding")
                    })
                })
    
    opened by ppg408331701 4
  • 关于多个fragment共用一个viewmodel的情况

    关于多个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内的数据库的操作对象吗?

    opened by ppg408331701 4
  • issue

    issue

    我想问一个问题哈。LoadSir我用的时候 setDefaultCallback(SuccessCallback::class.java)//设置默认加载状态页 如果用SuccessCallback的话在调用LoadSir.showLoading()的时候,Progressbar并不能显示出来,请问你是怎么设置的?

    opened by hanayokana 3
  • 有什么方法可以  代替 onresume吗?

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

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

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

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

    opened by ppg408331701 3
  •  Caused by: java.lang.reflect.InvocationTargetException

    Caused by: java.lang.reflect.InvocationTargetException

    当我在该框架上使用大疆sdk时,我遇到如下问题

     App has crashed, executing CustomActivityOnCrash's UncaughtExceptionHandler
                                                                                                        android.view.InflateException: Binary XML file line #18 in me.hgj.jetpackmvvm.demo:layout/fragment_home: Binary XML file line #18 in me.hgj.jetpackmvvm.demo:layout/fragment_home: Error inflating class dji.ux.widget.FPVOverlayWidget
                                                                                                        Caused by: android.view.InflateException: Binary XML file line #18 in me.hgj.jetpackmvvm.demo:layout/fragment_home: Error inflating class dji.ux.widget.FPVOverlayWidget
                                                                                                        Caused by: java.lang.reflect.InvocationTargetException
    

    这是错误截图 mvvm错误 为了验证我,下载了此项目,将 fragment.xml中加入如下代码 <dji.ux.widget.FPVOverlayWidget android:id="@+id/fpv_overlay_widget" android:layout_width="match_parent" android:layout_height="match_parent" />

    微信截图_20221103131446

    我增加了以下依赖 微信截图_20221103131504

    当我使用以下封装时可以正常使用viewbinding val aClass = (superclass as ParameterizedType).actualTypeArguments[0] as Class<*> try { val method = aClass.getDeclaredMethod("inflate", LayoutInflater::class.java) binding = method.invoke(null, layoutInflater) as T setContentView(binding!!.root) } catch (e: Exception) { e.printStackTrace() } 我不是很清楚您的封装问题出在哪里

    opened by fail572872916 2
  • okHttpClient 单例化

    okHttpClient 单例化

    在有些项目中, 网络请求可能不止一个apiService,很有可能是多个api,如UserApiService, OrderApiService,BuyCartApiService,再Api单例化的时候,okHttpClient 会创建多个对象,影响性能。因此okHttpClient 需要单例化。当然在此项目中只有一个apiService,并没有此问题。

    opened by ruirui1128 0
Releases(1.2.7)
Owner
鸡你太美
唱、跳、rap、篮球 🐔🏀
鸡你太美
Example Jetpack Compose Android App, that uses the newest mechanisms, like StateFlow, SharedFlow, etc. to manage states and handle events. ViewModel, UI and Screenshot tests included :)

AndroidMVIExample Example Jetpack Compose Android App, that uses the newest mechanisms, like StateFlow, SharedFlow, etc. to manage states and handle e

Patryk Kosieradzki 55 Nov 18, 2022
Android weather app using Hilt, Coroutines, Retrofit, Jetpack (Compose, Room, ViewModel) based on MVVM architecture

Atmostate A weather app written with Jetpack Compose using OpenWeatherMap Get the APK Features offline caching fetching data for current user location

Ramzan Sheikh 114 Dec 5, 2022
ViewModel-Lifecycle - ViewModel Lifecycle allows you to track and observe Jetpack ViewModel's lifecycle changes

ViewModel Lifecycle ?? ViewModel Lifecycle allows you to track and observe Jetpa

Jaewoong Eum 97 Nov 25, 2022
Viewmodel-lifecycle - ViewModel Lifecycle allows you to track and observe Jetpack ViewModel's lifecycle changes

ViewModel Lifecycle ?? ViewModel Lifecycle allows you to track and observe Jetpa

Jaewoong Eum 36 Feb 6, 2022
ViewModel LiveData Sample - Sample of using ViewModel, LiveData and Data Binding

ViewModel_LiveData_Sample Sample Code for Lesson 8 using ViewModel, LiveData and

null 0 Mar 18, 2022
MVVM(Model View ViewModel) sample in Kotlin using the components ViewModel, LiveData and Retrofit library

kotlin-mvvm Languages: English, Spanish MVVM(Model View ViewModel) sample in Kotlin using the components ViewModel, LiveData, the libraries Retrofit,

Eduardo José Medina Alfaro 466 Jan 5, 2023
LifecycleAwareGitHubSearch - The Activity Lifecycle and the ViewModel Architecture

Lifecycle-Aware GitHub Search In this project, we'll modify our GitHub search ap

null 1 Feb 8, 2022
Android To-Do MVVM Architecture App written in Kotlin.(ViewModel, ROOM, Livedata, Coroutines)

MVVM-To-Do-App A To-Do application written in kotlin using Android Architectural components What's new? Room + Coroutines - Upgraded Room to v2.1. Roo

Naveen T P 77 Dec 8, 2022
❤️ A sample Marvel heroes application based on MVVM (ViewModel, Coroutines, LiveData, Room, Repository, Koin) architecture.

MarvelHeroes MarvelHeroes is a demo application based on modern Android application tech-stacks and MVVM architecture. Fetching data from the network

Jaewoong Eum 1.2k Dec 19, 2022
🦁 A Disney app using transformation motions based on MVVM (ViewModel, Coroutines, Flow, LiveData, Room, Repository, Koin) architecture.

DisneyMotions A demo Disney app using transformation motions based on MVVM architecture. The motion system is included in the 1.2.0-alpha05 released m

Jaewoong Eum 1.4k Dec 16, 2022
❤️ A sample Marvel heroes application based on MVVM (ViewModel, Coroutines, LiveData, Room, Repository, Koin) architecture.

MarvelHeroes MarvelHeroes is a demo application based on modern Android application tech-stacks and MVVM architecture. Fetching data from the network

Jaewoong Eum 1.2k Dec 19, 2022
🦁 A Disney app using transformation motions based on MVVM (ViewModel, Coroutines, Flow, LiveData, Room, Repository, Koin) architecture.

DisneyMotions A demo Disney app using transformation motions based on MVVM architecture. The motion system is included in the 1.2.0-alpha05 released m

Jaewoong Eum 1.4k Jan 2, 2023
:cyclone: A Pokedex app using ViewModel, LiveData, Room and Navigation

Pokedex app built with Kotlin Download Go to the releases page to download the latest available apk. Screenshots Development Roadmap Kotlin LiveData N

Marcos Paulo Farias 1.4k Dec 28, 2022
🔥采用 Kotlin 语言编写,专为新手入门准备的项目。单Activity多Fragment,MVVM,ViewModel + LiveData + Retrofit + 协程, ViewBinding等等。拒绝过度设计和封装,项目结构清晰,代码简洁优雅。

前言 学习Kotlin有一段时间了,想写一个项目总结收获,就有了这个可能是东半球最简洁的玩安卓客户端,在此感谢玩Android 的开放API。 简介 采用 Kotlin 语言编写,专为新手入门准备的项目。单Activity多Fragment,MVVM,ViewModel + LiveData + R

zst 827 Dec 31, 2022
Sample app that implements MVVM architecture using Kotlin, ViewModel, LiveData, and etc.

TheShard is a project to showcase different architectural approaches to developing Android apps. In its different branches you will find the same app (A movie Listing and detail page) implemented with small differences.

null 17 Aug 19, 2021
Wallpaper app made using Hilt, Retrofit, Room, Navigation Components, MVI, Coroutines, Flows, ViewModel, LiveData, Datastore Preference.

Android Picture Engine Wallpaper app made using Hilt, Retrofit, Room, Navigation Components, MVI, Coroutines, Flows, ViewModel, LiveData, Datastore Pr

Simone Conigliaro 59 Sep 27, 2022
📝 Note List app based on MVVM architecture (ViewModel, LiveData, Coroutines, Room and Jetpack Compose)

Note list app built with Jetpack Compose Download Go to the releases page to download the latest available apk. Screenshots Architecture Features Home

Marcos Paulo Farias 45 Dec 25, 2022
🦄 Android Pokedex-AR using ARCore, Sceneform, Hilt, Coroutines, Flow, Jetpack (Room, ViewModel, LiveData) based on MVVM architecture.

?? Android Pokedex-AR using ARCore, Sceneform, Hilt, Coroutines, Flow, Jetpack (Room, ViewModel, LiveData) based on MVVM architecture.

Jaewoong Eum 535 Dec 9, 2022
📒Note taking app, MVVM with Google Architectural components Room, LiveData and ViewModel written in Kotlin, androidx libraries

?? MyNotes Note taking Android App using androidx libraries, MVVM with Google Architectural components Room, LiveData and ViewModel. Written in Kotlin

Akshat Bhuhagal 60 Dec 5, 2022
MarsRealEstate is a simple demo app using ViewModel & LiveData with Retrofit, Glide and Moshi in Kotlin.

Android-NASA-Real-Estate-Mars Is Android app that uses Kotlin and MVVM architecture is a simple app that uses Coroutines, LiveData with Retrofit, Glid

Dmytro K 0 Nov 17, 2021