MVVM stands for model view view-model pattern which helps to separate development of graphic user interface and remove lots of bboilerplatecodes. So in this blog we will help you to use MVVM architecture with rxjava and retrofit in Kotlin or we can say that we will going to implement following features in kotlin project:
- 100% Kotlin use
- Clean Android MVVM Architecture
- Retrofit service for network calls
- RxJava2 and Java8
Lets see how:
- Add kotlin support while create new project
- Add following dependencies in your app.gradle for Retrofit, RxJava and MVVM support :
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.jakewharton.rxbinding:rxbinding:0.4.0'
implementation 'com.google.code.gson:gson:2.8.0'
implementation "android.arch.lifecycle:extensions:1.1.1"
annotationProcessor "android.arch.lifecycle:compiler:1.1.1"
3. Add following compile option to include java8 lambda expressions inside android tag in app.gradle:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
4. Create api interface to define api call :
interface ApiInterface {
@GET("android")
fun getAndroid(): Call<List<Android>>
}
5. Create a model class to hold android versions data, In Kotlin we used data class to hold data :
data class Android(
val name : String,
val apiLevel : String)
6. Now we create a viewmodel class that will work as a bridge between view and model, it basically prepare observable and that can be observe by view:
class AndroidViewModel: ViewModel() {
private val mService = RetrofitService()
fun getAndroidData() : MutableLiveData<List<Android>>? {
Log.e("getAndroidData","yes")
return mService.loadAndroidData()
}
}
7. Now create a common service class for retrofit where we will create a singleton class by using companion object so that only a single instance of Retrofit will generate and method will return a mutable livedata that can be observe by view:
class RetrofitService {
val liveUserResponse: MutableLiveData<List<Android>> = MutableLiveData()
companion object Factory {
var gson = GsonBuilder().setLenient().create()
fun create(): ApiInterface {
Log.e("retrofit","create")
val retrofit = Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl("https://learn2crack-json.herokuapp.com/api/")
.build()
return retrofit.create(ApiInterface::class.java)
}
}
fun loadAndroidData(): MutableLiveData<List<Android>>? {
Log.e("loadAndroidData","yes")
val retrofitCall = create().getAndroid()
retrofitCall.enqueue(object : Callback<List<Android>> {
override fun onFailure(call: Call<List<Android>>, t: Throwable?) {
Log.e("on Failure :", "retrofit error")
}
override fun onResponse(call: Call<List<Android>>, response: retrofit2.Response<List<Android>>) {
val list = response.body()
for (i in list.orEmpty()){
Log.e("on response 1:", i.name)
}
liveUserResponse?.value = list
Log.e("hasActiveObservers 1", liveUserResponse?.hasActiveObservers().toString()+" check")
Log.e("on response 2 :", liveUserResponse.toString()+" check")
}
})
return liveUserResponse
}
}
we are using learn2crack api to show all android versions in a recyclerview.
8. MainActivity to show android versions in a recyclerview :
class MainActivity : AppCompatActivity() {
private lateinit var linearLayoutManager: LinearLayoutManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
linearLayoutManager = LinearLayoutManager(this@MainActivity)
recyclerView.layoutManager = linearLayoutManager
recyclerView.hasFixedSize()
getAndroidVersion()
}
private fun getAndroidVersion() {
Log.e("getAndroidVersion","yes")
val mAndroidViewModel = ViewModelProviders.of(this@MainActivity).get(AndroidViewModel::class.java)
mAndroidViewModel.getAndroidData()?.observe(this, Observer<List<Android>> { androidList ->
Log.e("list",androidList?.size.toString())
recyclerView.adapter = EmpAdapter(this@MainActivity, androidList as ArrayList<Android>, object : ItemClickListener {
override fun onItemClick(pos: Int) {
Toast.makeText(applicationContext, "item $pos clicked", Toast.LENGTH_LONG).show()
}
})
})
}
}
9. Now creating adapter to fill data in recyclerview, here we will use rxjava click feature
class EmpAdapter(var context: MainActivity, var mEmpList: ArrayList<Android>, private val itemClick:ItemClickListener): RecyclerView.Adapter<EmpAdapter.EmpHolder>() {
companion object {
var mItemClickListener : ItemClickListener? = null
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EmpHolder {
val view = LayoutInflater.from(context).inflate(R.layout.items, parent, false)
return EmpHolder(view)
}
override fun getItemCount(): Int {
return mEmpList.size
}
override fun onBindViewHolder(holder:EmpHolder, position: Int) {
mItemClickListener = itemClick
holder.tvFname?.text = mEmpList[position].name
holder.tvLname?.text = mEmpList[position].apiLevel
RxView.clicks(holder.mView).subscribe {
mItemClickListener!!.onItemClick(position)
}
}
class EmpHolder (view: View) : RecyclerView.ViewHolder(view) {
val tvFname = view.tvFname
val tvLname = view.tvLname
val mView = view
}
}
10. Interface for click event :
interface ItemClickListener {
fun onItemClick(pos : Int)
}
You can also download the whole sample project here :
https://github.com/rohitpuriji/Kotlin-MVVM
Post you comment for any query.
Thanks.
0 Comment(s)