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 fun create(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