Join the social network of Tech Nerds, increase skill rank, get work, manage projects...
 
  • How to use MVVM Architecture with rxjava and retrofit in Kotlin

    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 12.3k
    Comment on it

    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:

    1. 100% Kotlin use
    2. Clean Android MVVM Architecture
    3. Retrofit service for network calls
    4. RxJava2 and Java8

     

    Lets see how:

    1. Add kotlin support while create new project
    2. 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)

Sign In
                           OR                           
                           OR                           
Register

Sign up using

                           OR                           
Forgot Password
Fill out the form below and instructions to reset your password will be emailed to you:
Reset Password
Fill out the form below and reset your password: