RecyclerView 是一款很是強大的 widget,它能夠幫助您靈活地顯示列表數據。當我開始學習 RecyclerView 的時候,我發現對於複雜的列表界面有不少資源能夠參考,可是對於簡單的列表展示就鮮有可參考的資源了。雖然 RecyclerView 的組成結構乍一看有些複雜,可是深刻理解之後您會發現它其實很是簡單明瞭。android
本文會經過建立一個簡單的 RecyclerView 實現一個列表來顯示不一樣種類的花的名字。在實現的過程當中,我也會將 RecyclerView 的每一個部分揉碎了展示給你們,這樣你們就能夠在本身的應用中實現了。git
RecyclerView 是一個容器,它用於顯示列表形式 (list) 或者網格形式 (grid) 的數據,好比文本或者照片。github
當列表滑動的時候,實際上只有少許鄰近的視圖會顯示在屏幕上。當視圖滑出屏幕時,RecyclerView 會複用它而且填充新的數據。因爲它是經過回收已有的結構而不是持續建立新的列表項,因此它能夠有效提升應用的時間效率和空間效率。數據庫
粉紅色的方格表示屏幕上正在顯示的表項,黃色的方格表示屏幕可視範圍以外的表項是如何被回收並轉爲新的視圖
爲何您須要使用 RecyclerView 呢?數組
總之,RecyclerView 兼顧了靈活性和個性化,因此它是功能強大的工具。緩存
本文會爲你們展現如何實現一個簡單的 RecyclerView
,用它來顯示不一樣種類花的名稱。下面的代碼會使用 Kotlin 語言,可是 RecyclerView
也能夠在 Java 語言中使用。網絡
首先在 Android Studio 裏建立一個工程,而且使用 Empty Activity 模板。設置項目名稱,而且選擇 Kotlin 做爲項目所用的語言。app
接下來在 app 級的 build.gradle
文件裏引入 最新版本 的 RecyclerView
依賴。ide
2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> // 在 https://developer.android.google.cn/jetpack/androidx/releases/recyclerview 得到最新版本號 def recyclerview_version = "1.1.0" implementation 'androidx.recyclerview:recyclerview:$recyclerview_version
RecyclerView
最重要的組成部分之一就是須要顯示的數據。對於比較複雜的應用來講,數據多是來自數據庫或者來自於網絡,不過這裏咱們簡單使用字符串資源文件做爲應用的數據源。函數
在 strings.xml
文件中,建立一個字符串數組來存放花的名稱。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> <resources> <string name="app_name">RecyclerSample</string> <string-array name="flower_array"> <item>Lily</item> <item>Poppy</item> <item>Sunflower</item> <item>Freesia</item> <item>Daisy</item> <item>Rose</item> <item>Daffodil</item> <item>Lavender</item> <item>Peony</item> <item>Lilac</item> <item>Dahlia</item> <item>Tulip</item> <item>Dandelion</item> <item>Geranium</item> <item>Gardenia</item> <item>Rhododendron</item> <item>Azalea</item> </string-array> </resources>
而後,建立一個類,名字爲 Datasource
,而且能夠接收一個 Context 類型的參數。建立一個叫作 getFlowerList()
的函數,它負責返回花的名稱列表。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> class Datasource(val context: Context) { fun getFlowerList(): Array<String> { return context.resources.getStringArray(R.array.flower_array) } }
在 MainActivity.onCreate()
中,建立一個變量叫作 flowerList
,而後將 getFlowerList()
的返回結果賦給它。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val flowerList = Datasource(this).getFlowerList() }
接下來,在 activity_main
佈局文件中將 TextView
替換爲 RecyclerView
,而且將其 layoutManager
設置爲 LinearLayoutManager
。使用 LinearLayoutManager
意味着將來數據將以縱向列表或者橫向列表的形式顯示 (默認是縱向列表)。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutManager="LinearLayoutManager"/> </FrameLayout>
上面的示意圖表示一個包含數據表項的 RecyclerView
。在這裏,組成 RecyclerView
的表項 (Item) 裏會包含花的名稱。
建立一個新的佈局文件,將它命名爲 flower_item
,它用來決定每個表項的顯示佈局。本例中佈局僅須要顯示一個鮮花的名稱,因此這裏只須要 TextView
。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/flower_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="32sp" /> </FrameLayout>
接下來是 RecyclerView
的重頭戲了,也就是 ViewHolder 和 Adapter 類。ViewHolder 負責存儲 RecyclerView 中每個單獨的表項所須要顯示的信息。RecyclerView 僅須要建立當前所顯示的表項數量的 ViewHolder 外加緩存中的幾個 ViewHolder 便可。隨着用戶滑動屏幕,ViewHolder會被回收 (使用新數據進行填充),已有的表項會在一端消失,而且在另外一端顯示一個新的表項。Adapter 類從數據源得到數據,而且將數據傳遞給正在更新其所持視圖的 ViewHolder。下圖顯示了 RecyclerView、Adapter、ViewHolder 和數據之間的協做關係。
建立 Adapter
建立一個叫作 FlowerAdapter 的類,所需顯示的列表數據做爲該類的參數。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> class FlowerAdapter(val flowerList: Array<String>) { }
建立 ViewHolder
建立一個叫作 FlowerViewHolder 的內部類,而且它能夠接收一個 itemView 做爲參數。在 ViewHolder 中,建立一個變量來引用 TextView,而後將它指向表項佈局裏對應的視圖。而後建立 bind() 函數,它用來將花的名字 (字符串) 和攜帶數據的 UI (flowerTextView) 關聯起來。bind() 函數接收傳入的字符串,而且將字符串做爲 flowerTextView 的文本內容。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> class FlowerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){ private val flowerTextView:TextView = itemView.findViewById(R.id.flower_text) fun bind(word: String){ flowerTextView.text = word } }
繼承 RecyclerView.Adapter
更新 FlowerAdapter 的類定義,使其繼承 RecyclerView.Adapter 類,而且將 FlowerViewHolder做爲參數傳入。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> class FlowerAdapter(val flowerList: Array<String>) : RecyclerView.Adapter<FlowerAdapter.FlowerViewHolder>() { }
重寫 RecyclerView.Adapter
的類須要重寫三個方法 onCreateViewHolder()
、onBindViewHolder()
和 getItemCount()
。
重寫 onCreateViewHolder()
當 ViewHolder
建立的時候會調用該方法。在該方法裏進行初始化和填充 RecyclerView
中的表項視圖。該視圖使用前面咱們建立的用於顯示文本的佈局。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FlowerViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.flower_item, parent, false) return FlowerViewHolder(view) }
重寫 onBindViewHolder()
onBindViewHolder()
被調用的時候,會傳入參數 ViewHolder
和一個位置 (position),它表示在 flowerList 中所綁定的表項的位置。該位置能夠用於提取表項所需的數據,而且將數據傳遞給 ViewHolder 來使數據綁定到對應的 UI。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> override fun onBindViewHolder(holder: FlowerViewHolder, position: Int) { holder.bind(flowerList[position]) }
重寫 getItemCount()
RecyclerView 顯示一個列表,因此它須要知道列表裏共有多少項。因爲 flowerList 就是數據源,因此直接返回它的長度便可。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> override fun getItemCount(): Int { return flowerList.size }
完成 Adapter 代碼
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> class FlowerAdapter(val flowerList: Array<String>) : RecyclerView.Adapter<FlowerAdapter.FlowerViewHolder>() { // 描述表項視圖而且將它放在 RecyclerView 中 class FlowerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { private val flowerTextView: TextView = itemView.findViewById(R.id.flower_text) fun bind(word: String) { flowerTextView.text = word } } // 返回一個新的 ViewHolder override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FlowerViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.flower_item, parent, false) return FlowerViewHolder(view) } // 返回數據列表的長度 override fun getItemCount(): Int { return flowerList.size } // 顯示一個指定位置的數據 override fun onBindViewHolder(holder: FlowerViewHolder, position: Int) { holder.bind(flowerList[position]) } }
咱們已經建立了佈局、數據列表和 adapter。如今咱們能夠將 RecyclerView
添加到 MainActivity
,而且將 Adapter
賦值給它。
定義一個變量叫作 recyclerView
,而後將 activity_main
中的 RecyclerView
賦值給 recyclerView
。將 FlowerAdapter
做爲您 recyclerView
的 adapter。
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val flowerList = Datasource(this).getFlowerList() val recyclerView: RecyclerView = findViewById(R.id.recycler_view) recyclerView.adapter = FlowerAdapter(flowerList) } }
如今咱們運行一下,而後看看它操做起來如何:
完整代碼請點擊 這裏。
上面的例子爲你們展現瞭如何實現 RecyclerView 的幾個組成部分來顯示簡單的文本元素。固然 RecyclerView 能夠包含更多有趣和複雜的元素,咱們將在將來的文章和示例中爲你們展現。
更多資源,請參閱: