Android RecyclerView Kotlin

使用Kotlin實作RecyclerView及RecyclerView的優點

羅峰廷 2019/07/24 19:07:45
6826

前言:

說起RecyclerView,其實他已經出生很久,在2014I/O大會就推出了,我認為google有意要讓他取代傳統的ListView,而這裡要跟大家介紹他的實作方法,以及和ListView不同的優勢。

 

內文:

iOS必學元件列表裡面,有一個叫做UITableView,與其在Android相對應的就是ListView了,但其實UITableView有容易實作的reuse cell機制,而ListView沒有。不過現在有能自動回收,並且實作起來更方便的RecyclerView,而且基礎的寫法跟ListView很像,以下是RecyclerView的基本架構:

 

1.先拉個RecyclerView進來,並賦予他id

 

2.RecyclerView也是使用Adapter來串接資料,所以要新增一個繼承RecyclerView.Adapter<ViewHolder>的類別

另外,需要新增一個類別繼承RecyclerView.ViewHolder,其內部需定義Cell內用到的元件

class TestAdaper : RecyclerView.Adapter<TestAdaper.ViewHolder> {
    private var context:Context

    constructor(context: Context) : super() {
        this.context = context
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
       
    }

    override fun getItemCount(): Int {
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {

    }

    class ViewHolder : RecyclerView.ViewHolder {
        constructor(itemView: View) : super(itemView)
    }

}

 

3. 新增一個Layout來定義Cell的長相

 

 

4.將需要用的元件都定義在ViewHolder內,並請在變數前面加上lateinit,否則沒有初始化會出現編譯錯誤

    class ViewHolder : RecyclerView.ViewHolder {
        lateinit var nameTextView:TextView
        lateinit var imageView:ImageView
        lateinit var videoBtn:ImageView

        constructor(itemView: View) : super(itemView)
    }

 

5. 新增一個簡單的Model來定義資料內容

class TestModel {
    var name:String
    var imageUrl:String
    var videoUrl:String

    constructor(name: String, imageUrl: String, videoUrl: String) {
        this.name = name
        this.imageUrl = imageUrl
        this.videoUrl = videoUrl
    }
}

6.有了Cell跟Model,就可以在Adapter內做對應的顯示,另外,我這裡使用Glide來處理圖片,詳細請到他的網站看看

private var data:Array<TestModel>

    constructor(context: Context, data: Array<TestModel>) : super() {
        this.context = context
        this.data = data
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val cell = LayoutInflater.from(context).inflate(R.layout.view_cell, parent, false)
        val viewHolder = ViewHolder(cell)
        cell.layoutParams.height = 300
        viewHolder.imageView = cell.findViewById(R.id.imageView)
        viewHolder.nameTextView = cell.findViewById(R.id.nameTextView)
        viewHolder.videoBtn = cell.findViewById(R.id.videoBtn)
        return viewHolder
    }

    override fun getItemCount(): Int {
        return data.size
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val model = data[position]
        Glide.with(context).load(model.imageUrl).into(holder.imageView)
        holder.nameTextView.setText(model.name)
        holder.videoBtn.setOnClickListener {
            AlertDialog.Builder(context).setMessage(model.videoUrl).setCancelable(true).create().show()
        }
    }

7.在Activity將Adapter初始化,並且放進資料,再指定給RecyclerView,

而這裡有個與ListView不同的地方是,RecyclerView需要一個LayoutManager來定義有關排版方面的需求,

若有特別需要也可以寫一個繼承LayoutManager的類別來實作,這裡用最基本的LinearLayoutManager來示範

private fun initView(){
    val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
    val linearLayoutManager = LinearLayoutManager(this)
    val testAdapter = TestAdaper(this, array)
    recyclerView.layoutManager = linearLayoutManager
    recyclerView.adapter = testAdapter
}

 

畫面結果就會這樣呈現

 

RecyclerView的優點:

1.可以利用LayoutManager輕鬆地處理排版,例如需要將表格的滾動方式改成橫向,只需要加入一行程式

linearLayoutManager.orientation = RecyclerView.HORIZONTAL

2.在ListView中,資料有更新之後,可以呼叫一個方法來更新版面,而RecyclerView除了這點,還支援部份更新

    findViewById<Button>(R.id.updateButton).setOnClickListener({
        updateLastModel()
        testAdapter.notifyItemChanged(array.size - 1)
    })
    private fun updateLastModel(){
        val model = array.last()
        model.name = "UNO"
        model.imageUrl = "https://store-images.s-microsoft.com/image/apps.64833.67582047191807640.1f6942f5-d7bc-46df-a9db-2fa15b28dfdf.7d799b05-0ec4-4758-92ac-c4152b49db91"
        model.videoUrl = "UNO的教學影片"
    }

按下按鈕就可以達到部分更新的效果

3. RecyclerView會自動 Reuse Cell,如果在Adapter內Create跟Bind的地方加上Log,可以發現上下滾動之後,都不會進去Create的方法了

另外還有內建簡單的動畫,加入HeaderView&FooterView,OnItemTouchListener等等許多優點,這裡就不一一說明

總結:

RecyclerView 比起ListView定義了更嚴謹的ViewHolder,也需要另外用 LayoutManager來定義其版面種類,

但也更方便實作較複雜的排版,SDK也內建Grid、StaggeredGrid等LayoutManager,這些常見的版面,

效能上也提升不少,對大量資料呈現的App會是很好用的元件。

 

羅峰廷