At Flutter Live 2018 on December 5th, Google announced the official release of Flutter 1.0. Dart is a mobile development platform designed to help developers develop high quality native app interfaces on both iOS and Android. In addition, Google has announced an experimental Web-based implementation of the Flutter runtime that aims to bring Flutter applications to standard Web browsers.


Ya ya. Jpeg

Ya-ya is beautiful. Kotlin smells good

Here is a simple and practical introductionRecyclerAdapterThe encapsulation

It’s almost impossible not to use RecyclerView in your daily development, but it would be extremely painful to manually implement an Adapter every time. Each fixed copy of its three methods is also very helpless, so the author wants to package a simple and use Adapter, to meet the daily development needs, but not redundant. In the process of using Kotlin encapsulation, further experience the charm of Kotlin language.

Important methods and classes
  1. GetItemCount () : Returns an Int representing the length of the list

  2. OnCreateViewHolder (parent: ViewGroup, viewType: Int): BaseHolder: Get the View object from the item layout and return the ViewHolder object we need

  3. OnBindViewHolder (holder: BaseHolder, position: Int) : Pass the current item data to the ViewHolder internal controller using position

  4. Recyclerview. ViewHolder(itemView) : Use the obtained data to manipulate the itemView and its child views

Override and inherit the above methods and classes

The entire code wrapped into the ViewHolder is first posted

package com.taonce.onitemclick.BaseAdapter import android.support.v4.util.SparseArrayCompat import android.support.v7.widget.RecyclerView import android.view.View import org.jetbrains.anko.find /** * Author: Taoyongxiang * Date: 2018/12/4 * Project: BaseAdapter * Desc: RecyclerView.ViewHolder Base class */ BaseHolder(itemView: View) : Recyclerview. ViewHolder(itemView) {// SparseArrayCompat is used to reuse the view, Private val mViews = SparseArrayCompat<View>() /** * convert the View to a specific View: */ fun <V: View> getView(id: Int): V { var view = mViews[id] if (view == null) { view = itemView.find(id) mViews.put(id, view) } return view as V } }Copy the code

There are two main uses in BaseHolder:

  1. SparseArrayCompat is a utility class provided by Android. It can be used to replace HashMap for object storage, so that we can reuse View efficiently every time we do not need to find.

    Find is the Anko library in Kotlin instead of findViewById().

  2. The as operator in Kotlin is very powerful. For example, the as operator returns an ImageView. When using this T, we can call the ImageView method without having to force it:

Val image = holder.getView<ImageView>(R.idtem_image) image.setimageresource (R.mimap.ic_launcher)Copy the code

Next, let’s look at the overall code that wraps the Adapter:

package com.taonce.onitemclick.BaseAdapter import android.content.Context import android.support.v7.widget.RecyclerView import android.util.Log import android.view.LayoutInflater import android.view.ViewGroup /** * Author: taoyongxiang * Date: 2018/12/4 * Project: BaseAdapter * Desc: RecyclerAdapter BaseAdapter<T>(private val CTX: Context, private val layoutRes: Int, val mData: MutableList<T>) : RecyclerView.Adapter<BaseHolder>() { private lateinit var mListener: OnItemClickListener private lateinit var mLongListener: OnItemLongClickListener fun setOnItemClickListener(mListener: OnItemClickListener) { this.mListener = mListener } fun setOnItemLongClickListener(mLongListener: OnItemLongClickListener) {this.mlongListener = mLongListener} /** * The binding between the data and item is given to the convert() method, */ Override fun onBindViewHolder(holder: BaseHolder, position: Int) { convert(holder, position) holder.itemView.setOnClickListener { mListener.onItemClick(position) } holder.itemView.setOnLongClickListener {mLongListener. OnItemLongClick (position)}} / * * * through layout id ViewHolder object * / override fun onCreateViewHolder (the parent:  ViewGroup, viewType: Int): BaseHolder { return BaseHolder(LayoutInflater.from(ctx).inflate(layoutRes, parent, false)) } override fun getItemCount(): Int {return mdata. size} /** * Abstract method used to implement logic for specific Adapter */ abstract fun convert(holder: BaseHolder, position: Int) /** * addData * item: addData * position: default last item */ fun addData(item: T, position: Int = mdata.size) {mdata.add (position, item) notifyDataSetChanged()} /** * Add data * listData: add data * isDelete: */ fun addListData(listData: MutableList<T>, isDelete: Boolean) {if (isDelete) {mdata.clear ()} mdata.addall (listData) notifyDataSetChanged()} /** * Delete the specified item data * position: start from 0  */ fun deletePositionData(position: If (position >= 0 && position < mdata.size) {mdata.remove (mData[position]) notifyDataSetChanged() } else { Log.d("taonce", "delete item failed, position error!" ** * deleteAllData */ fun deleteAllData(){mdata.removeall (mData) notifyDataSetChanged()} /** * click event */ interface OnItemClickListener { fun onItemClick(position: Int OnItemLongClickListener {fun onItemLongClick(position: Int): Boolean}}Copy the code

In BaseAdapter, the generic T is also used, which represents the type of the data source.

It mainly realizes the following functions:

  1. The OnItemClickListener and OnItemLongClickListener interfaces are used for the click event and long press event of item respectively.

  2. AddData (item: T, position: Int = mdata.size) : Used to add an item to the list. The default position is the last one

  3. addListData(listData: MutableList

    , isDelete: Boolean) : add multiple entries to a list. Boolean isDelete: delete all entries from a list. To refresh the current interface, you need to reload the data. So we add a flag bit.

  4. DeletePositionData (position: Int) : This method deletes an item of data

  5. DeleteAllData () : Deletes all data from the list

Here we hand the bindings of both itemView and data to the convert(Holder: BaseHolder, Position: Int) method. Let’s look at the implementation:

package com.taonce.onitemclick import android.content.Context import android.util.Log import android.widget.Button import android.widget.ImageView import android.widget.TextView import com.taonce.onitemclick.BaseAdapter.BaseAdapter import com.taonce.onitemclick.BaseAdapter.BaseHolder import kotlin.random.Random /** * Author: taoyongxiang * Date: 2018/12/4 * Project: BaseAdapter * Desc: demo */ class MainAdapter(ctx: Context, layoutRes: Int, mData: MutableList<String>) : BaseAdapter<String>(ctx, layoutRes, mData) { override fun convert(holder: BaseHolder, position: TextView = holder.getView<TextView>(r.id.tem_text) text.text = this.mdata [position] // Button val Button = holder.getView<Button>(R.i.TEM_button) button.text = "${random.nextBoolean ()}" button.setOnClickListener { Log.d("taonce", $ImageView = holder.getView<ImageView>(r.i.tem_image) image.setImageResource(R.mipmap.ic_launcher) } }Copy the code

By implementing the BaseAdapter class and overwriting its convert() method, we get the subview of ItemView directly from the method and bind the data to it.

In the future, when we use Adapter, we will be able to rewrite so many methods in a simple step.

The method encapsulated in the Activity implementation
package com.taonce.onitemclick import android.os.Bundle import android.support.v7.app.AppCompatActivity import android.support.v7.widget.LinearLayoutManager import android.util.Log import android.view.View import com.taonce.onitemclick.BaseAdapter.BaseAdapter import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity(), View.OnClickListener { val mData = mutableListOf("1") val adapter = MainAdapter(this, R.layout.item, mData) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) bt_add.setOnClickListener(this) bt_addAll.setOnClickListener(this) bt_reduce.setOnClickListener(this) bt_deleteAll.setOnClickListener(this) RecyclerView. LayoutManager = LinearLayoutManager (this) recyclerView. Adapter = adapter / / click event adapter.setOnItemClickListener(object : BaseAdapter.OnItemClickListener { override fun onItemClick(position: Int) { Log.d("taonce", "click item position is $position, The value is ${mData [position]} ")}}) / / long press event adapter. SetOnItemLongClickListener (object: BaseAdapter.OnItemLongClickListener { override fun onItemLongClick(position: Int): Boolean { Log.d("taonce", "long click position is $position, value is ${mData[position]}") return true } }) } override fun onClick(p0: View?) { when (p0!! .id) {// Add a data r.i.d.t_add -> adapter.addData("add") // Add multiple data r.I.D.t_addAll -> adapter.addListData(mutableListOf("android", "ios", "kotlin", "flutter"), True) / / delete a data R.i db t_reduce - > adapter. DeletePositionData (0) / / delete all data R.i db t_deleteAll - > adapter. DeleteAllData ()} }}Copy the code

The renderings are as follows:




Simple implementation

The source code has been uploaded toGitHub

Write in the last

Everyone is not born strong, if you don’t work hard, how to prove yourself, come on!

Thank You!

–Taonce

If you find this article helpful, then tap your little finger and long press the QR code below to follow the wave. We are looking forward to your participation


Kotlin and Android knowledge public account