Android simple MVVM example
This is a demonstration of using Android architectural component ViewModel for a simple MVVM design pattern. It will use RxJava 2, RxKotlin, RxAndroid, Retrofit 2, etc. Github api will be used as example for calling REST service with Retrofit 2. https://api.github.com/users/google
1. Include this at the top of the app gradle file for kotlin compiler.
apply plugin: 'kotlin-kapt'
2. Added these dependencies in the app gradle file.
//Architecture component implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0' kapt 'androidx.lifecycle:lifecycle-compiler:2.0.0' //RxJava implementation "io.reactivex.rxjava2:rxandroid:2.0.1" implementation "io.reactivex.rxjava2:rxjava:2.1.3" implementation "io.reactivex.rxjava2:rxkotlin:2.1.0" // Retrofit 2 implementation 'com.squareup.retrofit2:retrofit:2.5.0' implementation "com.squareup.retrofit2:adapter-rxjava2:2.5.0" implementation 'com.squareup.retrofit2:converter-gson:2.5.0' implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0' implementation 'com.google.code.gson:gson:2.8.2'
3. Create utility classes for creating Retrofit rest service interface, repository and ViewModel factories.
RestUtil.kt
class RestUtil private constructor() { private val API_BASE_URL = "https://api.github.com/" val retrofit: Retrofit init { val interceptor = HttpLoggingInterceptor() interceptor.level = HttpLoggingInterceptor.Level.BODY val httpClient = OkHttpClient.Builder().addInterceptor(interceptor).build() val builder = Retrofit.Builder() .baseUrl(API_BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) retrofit = builder.client(httpClient).build() } companion object { private var self: RestUtil? = null val instance: RestUtil get() { if (self == null) { synchronized(RestUtil::class.java) { if (self == null) { self = RestUtil() } } } return self!! } } }
RepositoryFactory.kt
object RepositoryFactory { fun createGithubRepository() : GithubRespository { val githubApi = RestUtil.instance.retrofit.create(GithubApi::class.java) return GithubRespository(githubApi) } }
ViewModelFactory.kt
class ViewModelFactory(private val githubRespository: GithubRespository) : ViewModelProvider.NewInstanceFactory() { override funcreate(modelClass: Class ): T { return MainActivityViewModel(githubRespository) as T } }
4. Create data model, retrofit api interface, and repository.
GithubAccount.kt
data class GithubAccount( @SerializedName("login") var login : String = "", @SerializedName("id") var id : Int = 0, @SerializedName("created_at") var createdAt : String = "", @SerializedName("updated_at") var updatedAt : String = "")
GithubApi.kt
interface GithubApi { @GET("/users/{username}") fun getGithubAccount(@Path("username") username: String): Single> }
GithubRespository.kt
class GithubRespository(val githubApi: GithubApi) { fun fetchGithubAccount(name : String) : Observable{ return Observable.create { emitter -> githubApi.getGithubAccount(name) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { if (it.body() != null) { emitter.onNext(it.body()!!) } }, { it.printStackTrace() }) } } }
5. Create the ViewModel which uses repository to get data and emit the data to the view through LiveData.
class MainActivityViewModel(val githubRespository: GithubRespository) : ViewModel() { private val _githubAccount : MutableLiveData= MutableLiveData() val githubAccount : LiveData = _githubAccount fun getGithubAccount(name : String) { githubRespository .fetchGithubAccount(name) .subscribe { _githubAccount.postValue(it) } } }
6. Finally using the ViewModel in the View class, MainActivity.kt
class MainActivity : AppCompatActivity() { private lateinit var mainActivityViewModel : MainActivityViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) mainActivityViewModel = ViewModelProviders.of(this, ViewModelFactory(RepositoryFactory.createGithubRepository())).get(MainActivityViewModel::class.java) mainActivityViewModel.githubAccount.observe(this, Observer { tv_content.text = it.toString() }) mainActivityViewModel.getGithubAccount("google") } }
7. Make sure add the INTERNET permission in the manifest file.
8. The layout file for the MainActivity, activity_main.xml
Search within Codexpedia
Search the entire web