Kotlin multimethod callback simplification (Lambda expression, recyclerView callback)

  • kotlin (RecyclerView) multiple method callbacks, single method callbacks use Lambda expression to simplify

Using your favorite RecyclerView as an example, to record the simplification of multiple and single callbacks in kotlin, kotlin is a really interesting language.

Of course, you can also write in java style, but the code is a bit bloated and does not reflect kotlin's uniqueness.This moment is recorded below.

 

  • 1. Unilateral Callback
  1. There is no need to define an interface, just one function variable
     
    lateinit var mListener: (String) -> Unit
    This is a function variable with a parameter of type String and no return value.
     
  2. adapter sets callback listening
     fun setListener(listener: (String) -> Unit) {
            this.mListener = listener
     }
    A parameter is a parameter defined above, a function variable with no return value
  • 2. Multi-method callback
  1. You need to define an interface first
     
        /**
         * Define a callback interface
         */
        interface SimpleCallback {
            fun onSuccess(response: String)
            fun onFailed(errorCode: Int, msg: String)
        }
    Two methods, successfully returning response, failed returning errorCode and msg
  2. By convention, define a builder
     
        /**
         * Define a Builder to simplify callback interfaces
         */
        class Builder : SimpleCallback {
    
            // Define a function variable
            private lateinit var onSuccessVal: (response: String) -> Unit
    
            // Assigning values to function variables
            fun onSuccessFun(listener: (response: String) -> Unit) {
                this.onSuccessVal = listener
            }
    
            // callback
            override fun onSuccess(response: String) {
                onSuccessVal.invoke(response)
            }
    
            //  Define a function variable
            private lateinit var onFailedVal: (errorCode: Int, msg: String) -> Unit
    
            // Assigning values to function variables
            fun onFailedFun(listener: (errorCode: Int, msg: String) -> Unit) {
                this.onFailedVal = listener
            }
    
            // callback
            override fun onFailed(errorCode: Int, msg: String) {
                onFailedVal.invoke(errorCode, msg)
            }
        }
  3. Function variable defining callback interface

     
        private lateinit var listener: SimpleCallback
  4. Set up callback monitoring

     
        fun setSimpleListener(listener: Builder.() -> Unit) {
            val builder = Builder()
            builder.listener()
            this.listener = builder
        }
  5. Define click method in adapter to call back
     
        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            holder.content.text = list[position]
            // This is click listening for a single callback function
            holder.content.setOnClickListener { this.mListener(holder.content.text as String) }
            // This is click listening for multiple callback methods
            holder.content.setOnClickListener {
                this.listener.onSuccess(holder.content.text as String)
                this.listener.onFailed(1, holder.content.text as String)
            }
        }

Finally, paste the code for Adapter and Active

  1. Adapter code

     
    class MyRecyclerViewAdapter : RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder>() {
    
        private var list: List<String> = listOf()
    
        override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
    
            val view: View = View.inflate(viewGroup.context, R.layout.item_recyclerview, null)
            return ViewHolder(view)
        }
    
        override fun getItemCount(): Int {
            return list.size
        }
    
        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            holder.content.text = list[position]
            // This is click listening for a single callback function
            holder.content.setOnClickListener { this.mListener(holder.content.text as String) }
            holder.content.setOnClickListener {
                this.listener.onSuccess(holder.content.text as String)
                this.listener.onFailed(1, holder.content.text as String)
            }
        }
    
        class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
            val content: TextView = view.findViewById(R.id.tv_con)
        }
    
    
        fun setData(list: List<String>) {
            this.list = list
            notifyDataSetChanged()
        }
    
    
    
        //This is a single function callback
    
        lateinit var mListener: (String) -> Unit
    
        fun setListener(listener: (String) -> Unit) {
            this.mListener = listener
        }
    
    
        private lateinit var listener: SimpleCallback
    
        fun setSimpleListener(listener: Builder.() -> Unit) {
            val builder = Builder()
            builder.listener()
            this.listener = builder
        }
    
    
        /**
         * Define a callback interface
         */
        interface SimpleCallback {
            fun onSuccess(response: String)
            fun onFailed(errorCode: Int, msg: String)
        }
    
    
        /**
         * Define a Builder to simplify callback interfaces
         */
        class Builder : SimpleCallback {
    
            // Define a function variable
            private lateinit var onSuccessVal: (response: String) -> Unit
    
            // Assigning values to function variables
            fun onSuccessFun(listener: (response: String) -> Unit) {
                this.onSuccessVal = listener
            }
    
            // callback
            override fun onSuccess(response: String) {
                onSuccessVal.invoke(response)
            }
    
            //  Define a function variable
            private lateinit var onFailedVal: (errorCode: Int, msg: String) -> Unit
    
            // Assigning values to function variables
            fun onFailedFun(listener: (errorCode: Int, msg: String) -> Unit) {
                this.onFailedVal = listener
            }
    
            // callback
            override fun onFailed(errorCode: Int, msg: String) {
                onFailedVal.invoke(errorCode, msg)
            }
        }
    
    
    }

     

  2. Activity Code
     
    package com.schema.kotlin_study
    
    import android.content.Context
    import android.support.v7.app.AppCompatActivity
    import android.os.Bundle
    import android.support.v7.widget.LinearLayoutManager
    import android.support.v7.widget.RecyclerView
    import android.util.Log
    import android.view.View
    import android.widget.Toast
    import java.util.concurrent.Executors
    
    class MainActivity : AppCompatActivity(), View.OnClickListener {
    
        var rvTest: RecyclerView? = null
        var myRecyclerViewAdapter: MyRecyclerViewAdapter? = null
        var list: MutableList<String> = ArrayList()
    
        override fun onClick(v: View?) {
            when (v?.id) {
                R.id.btn_add -> addData()
                R.id.btn_remove -> removeData()
            }
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            rvTest = findViewById(R.id.rv_test)
    
            initView()
            initData()
    
        }
    
        private fun initView() {
    
            myRecyclerViewAdapter = MyRecyclerViewAdapter()
            rvTest?.adapter = myRecyclerViewAdapter
            rvTest?.layoutManager = LinearLayoutManager(this)
    
            for (i in 0..10) {
                list.add(i.toString())
            }
            // Single function callback settings
            //myRecyclerViewAdapter?.setListener { Toast.makeText(this, it, Toast.LENGTH_SHORT).show() }
            // Multifunction callback settings, where you can implement a method or both
            myRecyclerViewAdapter?.setSimpleListener {
                onSuccessFun {
                    it.toast(this@MainActivity)
                    it.loge()
                  }
    
                onFailedFun { errorCode, msg ->
                    (errorCode.toString(10) + msg).toast(this@MainActivity)
                    (errorCode.toString(10) + msg).loge()
                }
            }
    
            /**  Here's just one way to implement it
            myRecyclerViewAdapter?.setSimpleListener {
                onSuccessFun {
                    it.toast(this@MainActivity)
                    it.loge()
                  }
            }*/
        }
    
        private fun initData() {
            myRecyclerViewAdapter?.setData(list)
        }
    
    
        private fun Any.toast(context: Context, duration: Int = Toast.LENGTH_SHORT): Toast {
            return Toast.makeText(context, this.toString(), duration).apply { show() }
        }
    
        private fun Any.loge(TAG: String = this@MainActivity.localClassName) {
            Log.e(TAG, this.toString())
        }
    
    }

     
  3. Finally, two tool classes, also extension functions, are pasted out, printing the log and displaying toast.You can use it as a top-level function, removing private s.
     
        private fun Any.toast(context: Context, duration: Int = Toast.LENGTH_SHORT): Toast {
            return Toast.makeText(context, this.toString(), duration).apply { show() }
        }
    
        private fun Any.loge(TAG: String = this@MainActivity.localClassName) {
            Log.e(TAG, this.toString())
        }

     

 

 

 

Tags: Android Java Lambda

Posted on Thu, 07 Nov 2019 08:26:40 -0800 by the_real_JLM