All Projects → DouiriAli → Android Architecture Components Kotlin

DouiriAli / Android Architecture Components Kotlin

Licence: mit
Clean code App with Kotlin and Android Architecture Components

Programming Languages

kotlin
9241 projects

Projects that are alternatives of or similar to Android Architecture Components Kotlin

Android Clean Architecture Mvvm Dagger Rx
Implemented by Clean Architecture, Dagger2, MVVM, LiveData, RX, Retrofit2, Room, Anko
Stars: ✭ 138 (+500%)
Mutual labels:  dagger2, clean-architecture, clean-code, room, retrofit2, livedata
Foodium
It simply loads Posts data from API and stores it in persistence storage (i.e. SQLite Database). Posts will be always loaded from local database. Remote data (from API) and Local data is always synchronized.
Stars: ✭ 1,940 (+8334.78%)
Mutual labels:  room, retrofit2, livedata, room-persistence-library, android-architecture-components
Base Mvvm
App built to showcase basic Android View components like ViewPager, RecyclerView(homogeneous and heterogeneous items), NavigationDrawer, Animated Vector Drawables, Collapsing Toolbar Layout etc. housed in a MVVM architecture
Stars: ✭ 18 (-21.74%)
Mutual labels:  dagger2, room, retrofit2, livedata, room-persistence-library
Android tmdb clean architecture
Showcase of clean architecture concepts along with Continuous Integration and Development for modular Android applications. Includes test suits (functional and unit tests) along with code coverage.
Stars: ✭ 63 (+173.91%)
Mutual labels:  dagger2, clean-architecture, android-architecture, room, retrofit2
movies
An example approach for modularization, reactive clean architecture and persistancy.
Stars: ✭ 110 (+378.26%)
Mutual labels:  room, clean-architecture, dagger2, retrofit2, livedata
GithubApp-android-architecture
Let's learn a deep look at the Android architecture
Stars: ✭ 16 (-30.43%)
Mutual labels:  clean-architecture, android-architecture, dagger2, retrofit2, livedata
News
A sample News 🗞 app built using Modern Android Development [Architecture Components, Coroutines, Retrofit, Room, Kotlin, Dagger]
Stars: ✭ 774 (+3265.22%)
Mutual labels:  dagger2, android-architecture, room, retrofit2, android-architecture-components
Githubprojectbrowser
This is a sample Android Project that is based on Clean Architecture
Stars: ✭ 64 (+178.26%)
Mutual labels:  dagger2, clean-architecture, room, retrofit2, livedata
News Sample App
A sample news app which demonstrates clean architecture and best practices for developing android app
Stars: ✭ 334 (+1352.17%)
Mutual labels:  dagger2, clean-architecture, room, retrofit2, livedata
Android Mvp Architecture
MVP + Kotlin + Retrofit2 + Dagger2 + Coroutines + Anko + Kotlin-Android-Extensions + RX-java + Mockk + Espresso + Junit5
Stars: ✭ 82 (+256.52%)
Mutual labels:  dagger2, clean-architecture, android-architecture, clean-code, retrofit2
Mvvmarms
Android MVVM Architecture Components based on MVPArms and Android Architecture Components.
Stars: ✭ 425 (+1747.83%)
Mutual labels:  dagger2, android-architecture, room, retrofit2, livedata
Fountain
Android Kotlin paged endpoints made easy
Stars: ✭ 175 (+660.87%)
Mutual labels:  dagger2, room, retrofit2, livedata, room-persistence-library
Mvvmframe
🏰 MVVMFrame for Android 是一个基于Google官方推出的Architecture Components dependencies(现在叫JetPack){ Lifecycle,LiveData,ViewModel,Room } 构建的快速开发框架。有了MVVMFrame的加持,从此构建一个MVVM模式的项目变得快捷简单。
Stars: ✭ 218 (+847.83%)
Mutual labels:  dagger2, room, retrofit2, livedata, android-architecture-components
Android-Clean-Architecture
🚀A basic sample android application to understand Clean Architecture in a very simple way and is written in Kotlin.
Stars: ✭ 39 (+69.57%)
Mutual labels:  clean-code, clean-architecture, android-architecture, dagger2
Superhero-App
🦸🏻‍♂️🦹🏻‍♀️Superhero app built with Kotlin, ViewModel, LiveData, ViewBinding, Room, and Hilt
Stars: ✭ 27 (+17.39%)
Mutual labels:  room, dagger2, retrofit2, livedata
flickr-android
A small sample app to showcase architecting app using Clean Architecture and MVVM
Stars: ✭ 25 (+8.7%)
Mutual labels:  room, clean-architecture, dagger2, retrofit2
Changedetection
Automatically track websites changes on Android in background.
Stars: ✭ 563 (+2347.83%)
Mutual labels:  dagger2, room, livedata, room-persistence-library
CleanArchitectureMVVM
Example of Clean Architecture of Android app using MVVM, Koin, Coroutines, Retrofit, Room, Solid Principle, DRY, KISS, OOP
Stars: ✭ 60 (+160.87%)
Mutual labels:  room, clean-code, clean-architecture, retrofit2
Simple-Note-App-with-Online-Storage
✍️ Simple Note Making App use Sqllite Room 🧰 for caching the notes and 📥 Firebase Database for online storage
Stars: ✭ 42 (+82.61%)
Mutual labels:  room, dagger2, livedata, room-persistence-library
UdacityPopularMovies
An Android app, that helps you browse most popular and most rated movies. This project is created for Udacity Android Developer Nanodegree.
Stars: ✭ 26 (+13.04%)
Mutual labels:  room, dagger2, retrofit2, android-architecture-components

You can support me buy contributing code, filing bugs, asking/answering questions, or buying me a coffee.

Buy Me a Coffee at ko-fi.com

Android Architecture Components with Kotlin

In this example we're building a UI that shows a github users.

Building the user interface

The UI will consist of a fragment UsersFragment.kt and its corresponding layout file fragment_users.xml.

We will create a UserViewModel.kt based on the ViewModel class to keep this information.

A ViewModel provides the data for a specific UI component, such as a fragment or activity, and handles the communication with the business part of data handling, such as calling other components to load the data or forwarding user modifications. The ViewModel does not know about the View and is not affected by configuration changes such as recreating an activity due to rotation.

Now we have 3 files.

fragment_users.xml: The UI definition for the screen.

UserViewModel.java: The class that prepares the data for the UI.

UsersFragment.java: The UI controller that displays the data in the ViewModel and reacts to user interactions.

Now, we have these three code modules, how do we connect them? After all, when the ViewModel's user field is set, we need a way to inform the UI. This is where the LiveData class comes in.

LiveData is an observable data holder. It lets the components in your app observe LiveData objects for changes without creating explicit and rigid dependency paths between them. LiveData also respects the lifecycle state of your app components (activities, fragments, services) and does the right thing to prevent object leaking so that your app does not consume more memory.

Every time the user data is updated, the onChanged callback will be invoked and the UI will be refreshed.

If you are familiar with other libraries where observable callbacks are used, you might have realized that we didn't have to override the fragment's onStop() method to stop observing the data. This is not necessary with LiveData because it is lifecycle aware, which means it will not invoke the callback unless the fragment is in an active state (received onStart() but did not receive onStop()). LiveData will also automatically remove the observer when the fragment receives onDestroy().

We also didn't do anything special to handle configuration changes (for example, user rotating the screen). The ViewModel is automatically restored when the configuration changes, so as soon as the new fragment comes to life, it will receive the same instance of ViewModel and the callback will be called instantly with the current data. This is the reason why ViewModels should not reference Views directly; they can outlive the View's lifecycle. See The lifecycle of a ViewModel.

Fetching data

Now we have connected the ViewModel to the fragment, but how does the ViewModel fetch the user data? In this example, we use a REST API of Github to retrieve the list of users. We will use the Retrofit library to access.

Here's our retrofit Webservice :

interface RemoteService {

    @GET("users")
    fun getUsersFromApi() : Observable<Response<List<UserResponse>>>
}

A naive implementation of the ViewModel could directly call the Webservice to fetch the data and assign it back to the user object. Even though it works, your app will be difficult to maintain as it grows. It gives too much responsibility to the ViewModel class which goes against the principle of separation of concerns that we've mentioned earlier. Additionally, the scope of a ViewModel is tied to an Activity or Fragment lifecycle, so losing all of the data when its lifecycle is finished is a bad user experience. Instead, our ViewModel will delegate this work to a new Repository module.

Repository modules are responsible for handling data operations. They provide a clean API to the rest of the app. They know where to get the data from and what API calls to make when data is updated. You can consider them as mediators between different data sources (persistent model, web service, cache, etc.)
class RepositoryDataSource constructor(private val remoteDataSource: RemoteDataSource) : Repository {

    private val data = MutableLiveData<List<UserEntity>>()

    override fun getUsersFromApi() : LiveData<User> {

        remoteDataSource.getUsersFromApi()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ result -> data.setValue(Transformation.toUsersEtities(result.body()!!)) },
                           { error -> Log.e(TAG, "{$error.message}") },
                           { Log.d(TAG, "completed") })

         return data;
    }

Connecting ViewModel and the repository

Now we modify our UserViewModel to use the repository.

class UserViewModel : ViewModel() {

    @Inject
    lateinit var mRepositoryDataSource : RepositoryDataSource

    init {

        App.mAppComponent.inject(this)
    }

    fun getUsers() : LiveData<List<UserEntity>> = mRepositoryDataSource.getUsersFromApi()

}

Persisting data

With the current implementation, we will need to fetch the data again from the network. This is not only a bad user experience, but also wasteful since it will use mobile data to re-fetch the same data. You could simply fix this by caching the web requests, but it creates new problems. What happens if the same user data shows up from another type of request (e.g., fetching a list of friends)? Then your app will possibly show inconsistent data, which is a confusing user experience at best. For instance, the same user's data may show up differently because the list-of-friends request and user request could be executed at different times. Your app needs to merge them to avoid showing inconsistent data.

The proper way to handle this is to use a persistent model. This is where the Room persistence library comes to the rescue.

Room is an object mapping library that provides local data persistence with minimal boilerplate code. At compile time, it validates each query against the schema, so that broken SQL queries result in compile time errors instead of runtime failures. Room abstracts away some of the underlying implementation details of working with raw SQL tables and queries. It also allows observing changes to the database data (including collections and join queries), exposing such changes via LiveData objects. In addition, it explicitly defines thread constraints that address common issues such as accessing storage on the main thread.

To use Room, we need to define our local schema. First, annotate the User class with @Entity to mark it as a table in your database.

@Entity(tableName = "users")
data class UserEntity(

        @PrimaryKey(autoGenerate = true)
         var id     : Long = 0,
         var name   : String,
         var avatar : String
)

Then, create a database class by extending RoomDatabase for your app:

@Singleton
@Database(entities = arrayOf(UserEntity::class), version = 1)
abstract class LocalDataSource : RoomDatabase() {}

Notice that LocalDataSource is abstract. Room automatically provides an implementation of it. See the Room documentation for details.

Now we need a way to get, insert and delete the users data into the database. For this, we'll create a data access object (DAO).

@Dao
interface UserDao {

    @Query("SELECT * FROM users")
    fun getUsers() : LiveData<List<UserEntity>>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun saveUsers(users : List<UserEntity>)

    @Query("DELETE FROM users")
    fun deleteUsers()
}

Then, reference the DAO from our database class.

@Singleton
@Database(entities = arrayOf(UserEntity::class), version = 1)
abstract class LocalDataSource : RoomDatabase() {

    abstract fun getUserDao() : UserDao

}

Notice that the load method returns a LiveData. Room knows when the database is modified and it will automatically notify all active observers when the data changes. Because it is using LiveData, this will be efficient because it will update the data only if there is at least one active observer.

Now we can modify our RepositoryDataSource to incorporate the Room data source.

class RepositoryDataSource constructor(private val remoteDataSource: RemoteDataSource,
                                       private val roomDataSource: LocalDataSource) : Repository {

    /**
     * Get users from database
     */
    override fun getUsersFromDb(): LiveData<List<UserEntity>> = roomDataSource.getUserDao().getUsers()

    /**
     * Get users from api
     */
    override fun getUsersFromApi() : LiveData<User> {

            remoteDataSource.getUsersFromApi()
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe({ result -> data.setValue(Transformation.toUsersEtities(result.body()!!)) },
                               { error -> Log.e(TAG, "{$error.message}") },
                               { Log.d(TAG, "completed") })

             return data;
        }

    /**
     * Save users into database
     */
    override fun saveUsers(users: List<UserEntity>) {

        roomDataSource.getUserDao().saveUsers(users)
    }

    /**
     * Delete all users
     */
    override fun deleteUsers() {

        roomDataSource.getUserDao().deleteUsers()
    }
}

Tools used on the sample project

Demo

Resources to start with Kotlin on Android

Resources to start with Android Architecture Components

Developed By

License

MIT License

Copyright (c) 2018 Ali DOUIRI

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].