Search code examples
androidkotlindata-bindingandroid-databindingandroid-livedata

How to change my existing code by integrating data binding android


I have an exisitng code which I integrate with Live data by using retrofit.

Now if I want to integrate databinding, where are all changes to be done to make the code looks perfect?

Here is my code.

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:background="#000000"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

    <LinearLayout
            android:id="@+id/linearLayout2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="vertical"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">


        <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="Android Versions"
                android:textColor="#ffffff"
                android:textSize="20sp" />
        <android.support.v7.widget.RecyclerView
                android:id="@+id/recyclerView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
    </LinearLayout>

 items.xml:


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:background="#445566"
        android:layout_margin="5dp"
        android:layout_height="wrap_content">

    <TextView
            android:id="@+id/tvFname"
            android:padding="5dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="top|start"
            android:layout_marginTop="8dp"
            android:textColor="#ffffff"
            android:layout_weight="1"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>

    <TextView
            android:id="@+id/tvLname"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center|start"
            android:padding="5dp"
            android:layout_marginTop="10dp"
            android:layout_weight="1"
            android:ellipsize="end"
            android:textColor="#ffffff"
            android:maxLines="5"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tvFname"/>


</android.support.constraint.ConstraintLayout>

Here is view model class which I integrated

class  AndroidViewModel:ViewModel() {
    private val mService = RetrofitService()

    fun getAndroidData():MutableLiveData<List<AndroidData>>?{
        return mService.loadAndroidData()
    }
}

Pojo class generated is just a simple one:

 data class AndroidData (val name:String, val apiLevel:String)

Service integration:

class RetrofitService {
    val liveUserResponse:MutableLiveData<List<AndroidData>> = 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<AndroidData>>? {

        Log.e("loadAndroidData","yes")

        val retrofitCall  = create().getAndroid()

        retrofitCall.enqueue(object : Callback<List<AndroidData>> {
            override fun onFailure(call: Call<List<AndroidData>>, t: Throwable?) {
                Log.e("on Failure :", "retrofit error")
            }

            override fun onResponse(call: Call<List<AndroidData>>, response: retrofit2.Response<List<AndroidData>>) {

                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
    }

Main Activity:

class MainActivity : AppCompatActivity(){

    private lateinit var linearLayoutManager: LinearLayoutManager
    override fun onCreate(savedInstanceState: Bundle?) {


        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        linearLayoutManager = LinearLayoutManager(this)
        recyclerView.setHasFixedSize(true)
        getAndroidVersion()
    }

    private fun getAndroidVersion() {
        Log.e("getAndroidVersion", "yes")

        val mAndroidViewModel = ViewModelProviders.of(this@MainActivity).get(AndroidViewModel::class.java)
        mAndroidViewModel.getAndroidData()?.observe(this, Observer<List<AndroidData>> { androidList ->

            Log.e("list", androidList?.size.toString())
            recyclerView.adapter = EmpAdapter(this@MainActivity, androidList as ArrayList<AndroidData>, object :
                ItemClickListener {
                override fun onItemClick(pos: Int, name:String) {
                    Toast.makeText(applicationContext, "item "+pos+ "clicked"+ name, Toast.LENGTH_LONG).show()
                }
            })
        })

    }

}

Adapter class:

class EmpAdapter(
    var context: MainActivity,
    var mEmpList: ArrayList<AndroidData>,
    private val itemClick:ItemClickListener
) :
    RecyclerView.Adapter<EmpAdapter.EmpHolder>() {
    override fun getItemCount(): Int {
        return mEmpList.size
    }
    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 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,mEmpList[position].name)
        }

    }




 class EmpHolder(view: View) : RecyclerView.ViewHolder(view) {
        val tvFname = view.tvFname
        val tvLname = view.tvLname
        val mView = view
    }
}

interfaces for retrofit:

interface ApiInterface {
    @GET("android")
    fun getAndroid(): Call<List<AndroidData>>
}

Now my question is, if I integrate tag and in xml, which variable i need to specify for textview to integrate to connect for textview in adapter? Kindly guide me where are all I need to change to apply, if I use live data


Solution

  • First of all, i strongly recommend to use a Retrofit Adapter that converts the response into LiveData automatically for you. See this example

    https://github.com/yasiralijaved/android-architecture-components/blob/master/component_http/src/main/java/com/yasiralijaved/android/arc/component/http/BackendService.java

    Secondly there are detailed tutorials out there which can surely help you how to implement Data Bindings in RecyclerView Adapter. A few tutorials are:

    1. https://medium.com/androiddevelopers/android-data-binding-recyclerview-db7c40d9f0e4
    2. https://android.jlelse.eu/how-to-bind-a-list-of-items-to-a-recyclerview-with-android-data-binding-1bd08b4796b4

    Do let me know if it is still not clear and i will share some more details.

    Happy coding!!