Recycler View คุณค่าที่คุณคู่ควร

Thirawat T.
4 min readAug 14, 2017

--

หากเราจะต้องทำแอปฯที่มีข้อมูลเรียงแถวกันเยอะๆ ไม่ว่าจะเป็นแนวตั้งหรือแนวนอน เราก็คงจะนึกถึง ListView กันเป็นอันดับแรกใช่ไหมครับ โดยการยัดทุกๆอย่างลงไปไว้ใน ListView เท่านี้ก็สามารถ scroll ดูข้อมูลไปมาได้ง่ายนิดเดียวเอง
แต่ถ้าหากว่าต้องการจะใส่ข้อมูล ที่มีข้อความ รูปภาพ และปุ่มไว้หรืออื่นๆอีกมากมายในแต่ละ List หรือจะเป็นการจัดตำแหน่ง view ที่ซับซ้อนหน่อย ListView เริ่มไม่ตอบโจทย์เราแล้วใช่ไหม
ผมเลยอยากจะขอแนะนำ Recycler View เพราะตัวมันแบ่งการทำงานออกอย่างชัดเจน การเขียนโค้ดเป็นไปใน Pattern ที่ดีและถูกต้อง เช่น การใส่ข้อมูล สร้าง view และแสดงผล อีกทั้งยังสามารถวาดอะไรบางอย่างให้กับ view นั้นๆได้ด้วย และสามารถสร้าง Animation ต่างๆให้กับ view ได้อีกด้วย ซึ่งตรงนี้แหละ ผมมองว่าเป็นจุดเปลี่ยนที่ทำให้ผมเลิกใช้ ListView ไปเลย…

ข้อดีของ Recycler View

  • หน้าตาของ List View กับ Recycler View นั้นไม่ต่างกัน แต่ว่าประสิทธิภาพในการทำงานของ Recycler View นั้นดีกว่า
  • ช่วยให้การเขียนโค้ดออกมาเป็น Pattern ที่ดีและถูกต้อง ลดความผิดพลาดจากการเขียนโค้ดใน List View ที่ชอบเขียนผิดวิธีกัน
  • มี LayoutManager, ItemDecoration และ ItemAnimation ช่วยให้การเขียนโค้ดจัดการการแสดงผลของ Recycler View แยกออกจากกันตามหน้าที่

การทำงานของ Recycler View

เราจะต้องมี Adapter เพื่อคอยจัดการระหว่างข้อมูลกับส่วนของการแสดงผลนั่นเอง
โดย Adapter ของนั้นจะมี method หลักๆด้วยกัน 3 method คือ
1. onCreateViewHolder : มีหน้าที่เพื่อให้เราสร้าง view ต่างๆแล้วเก็บไว้ใน ViewHolder อีกที
2. onBindViewHolder : มีหน้าที่จัดการข้อมูลที่ใส่เข้าไป เพื่อนำไปแสดงผล
บน view ตามที่ต้องการ เช่น ใส่ค่า String เข้าไป เพื่อนำไปแสดงผลบน textView หรือตอนที่มีการ scroll ข้อมูลใหม่เข้ามาแสดงผลบนหน้าจอ
3. getItemCount : มีหน้าที่บอกว่าเรามีข้อมูลที่ต้องการจะแสดงผลทั้งหมดกี่ชุด

เรามาสร้าง Recycler View กันเลยดีกว่าาา

ก่อนอื่นผมขออธิบายเกี่ยวกับการทำงานของ class ที่จะต้องเตรียมไว้คร่าวๆ ดังนี้

  • class Item : มีหน้าที่รับค่าต่างๆเข้าไป โดยหลักๆจะทำหน้าที่เป็น getter, setter
    และบอกว่าตัวเองต้องการเรียกใช้ view ไหน จากนั้นส่งต่อไปยัง Adapter
  • class Adapter : เรียกใช้ view ตามที่ class Item ต้องการและแสดงผลออกทางหน้าจอตามจำนวนชุดข้อมูลที่ถูกส่งมา
  • class ViewHolder : สร้าง view ต่างๆตามที่ Adapter เรียกใช้ และทำการเซ็ตค่าต่างๆลงไปใน view อีกด้วย เช่น เซ็ตค่าลงไปให้ TextView แสดงผลตามต้องการ

Class ทั้งหมดที่ใช้งาน

  • MainActivity.java
  • MainAdapter.java
  • BaseViewHolder.java
  • CardViewHolder.java
  • BaseItem.java
  • CardItem.java

เตรียมตัวก่อนเริ่มสร้าง
ทำการเพิ่ม dependencies ลงไปในไฟล์ build.gradle ที่อยู่ในระดับ app ลงไปก่อน

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:recyclerview-v7:25.3.1'
compile 'com.android.support:cardview-v7:25.3.1'
}

Note : ที่ต้องทำการเพิ่ม dependencies ของ cardview-v7:25.3.1 ลงไปด้วย เพราะว่าเราจะมีการใช้งาน CardView ด้วยนั่นเองครับ

จากนั้นกด Sync ให้เรียบร้อย แล้วไปลุยกันต่อเลยยยย

เตรียมไฟล์ Layout

activity_main.xml
activity_main.xml
list_item.xml

Note : สำหรับบางคนที่สงสัยว่า tools:src , tools:text และ tools:listitem ในไฟล์ activity_main.xml ว่ามันคืออะไร ?
tools อันนี้จะช่วยให้เราสามารถเห็นได้แค่ตอน Preview เท่านั้น แต่ตอนรันจริงๆจะมีผลอะไร และการที่จะใช้งาน tools ได้ ต้องมีการประกาศ xmlns:tools=”http://schemas.android.com/tools" ไว้ในไฟล์ .xml ด้วยนะ

list_item.xml

เตรียมไฟล์ Java

ViewType.java

class นี้เราจะทำการประกาศตัวแปรประเภทของ ViewHolder ไว้ในนี้ทั้งหมด โดยที่ adapter จะเช็คประเภทของ view แล้วเรียกใช้งาน ViewHolder อื่นๆได้เลย แต่ในตัวอย่างจะมีประเภทของ ViewHolder เพียงแค่ 1 ตัว คือ TYPE_CARD_VIEW
โดยการประกาศประเภทของ ViewHolder แยกไว้อีก class ต่างหาก ช่วยทำให้โค้ดของเรามีความยืดหยุ่น ไม่ไปผูกกับ class ใด class หนึ่งมากเกินไป และถ้าเผื่อในอนาคตอยากจะเพิ่มประเภทของ ViewHolder ก็สามารถมาเพิ่มที่ class นี้ได้เลย ทำให้หลายๆ class เรียกใช้งานได้อย่างอิสระอีกด้วย

Item

ในส่วนของ item เอาไว้จัดการ getter , setter โดยมีหน้าที่รับค่าต่างๆเข้ามา
จากนั้น ViewHolder จะเรียกใช้งานค่าต่างๆเพื่อนำไปแสดงผล และเอาไว้ return viewType ไปให้ adapter อีกด้วย

BaseItem.java
CardViewItem.java

ทำการ extends BaseItem ให้เรียบร้อย โดยถ้าหากต้องการจะสร้าง class Item เพิ่มก็สามารถสร้างแล้ว extends BaseItem ได้เลย ซึ่งวิธีนี้จะช่วยให้เวลาประกาศตัวแปร ArrayList มาใช้ ก็สามารถใช้ object เป็น BaseItem ได้เลยในทุกๆ class โดยที่ไม่ต้องใช้ของ class ใคร class มัน เช่น List<BaseItem> เป็นต้น
ในส่วนของ class Item ก็จะสร้าง method getter, setter สำหรับรับค่าและทุกครั้งที่มีการเรียกใช้ class CardViewItem ก็จะมีการส่งค่าไปยัง ViewType.java เพื่อบอกว่าตัวมันเองมีค่าเป็น view ประเภทไหนตามที่กำหนด
เพื่อที่เอาไว้ให้ adapter เรียกใช้งานได้ถูก

ViewHolder

BaseViewHolder.java
CardViewHolder.java

การที่ extends BaseViewHolder ก็เพื่อที่ว่าหากเราต้องการจะสร้าง ViewHolder เพิ่ม เราก็สามารถทำได้โดยการสร้าง ViewHolder และ extends BaseViewHolder ได้เลย

class นี้จะทำการสร้าง view เพื่อเตรียมไว้ใช้งาน โดยในตัวอย่างนี้จะมี ImageView และ TextView จากนั้นจะมี method setImage, setText เพื่อรับค่าเข้ามาแล้วทำการเซ็ตค่าให้กับ ImageView และ TextView

Adapter

MainAdapter.java

ใน method onCreateViewHolder จะทำหน้าที่เรียก layout ที่เราต้องการจะใช้
จากนั้น return view ไปยัง ViewHolder เพื่อทำการสร้าง view ที่ต้องการ

Note : ในกรณีที่ผมใช้ if ในการเช็ค viewType เอาไว้เผื่อในอนาคตมี layout
หลายตัวที่ต้องการเรียกใช้ ก็สามารถทำได้จากการเช็ค viewType แล้วจากนั้นก็ให้ return view ไปยัง ViewHolder ที่ต้องการได้เลย

onBindViewHolder : เราก็ทำการเช็ค ViewHolder โดยเช็คว่าถ้า holder เป็น object ของ CardViewHolder ถ้าใช่ ก็เรียก method setImage, setText เพื่อนำค่าที่เซ็ตเข้ามาผ่าน MainActivity ไปแสดงผลบนหน้าจอ
getItemCount : บอกจำนวนข้อมูลโดยดูจาก size ของ ArrayList นั่นเอง
getItemViewType : ทำการ return viewType ปกติ
setItemList : เป็นการกำหนดค่าให้กับ itemList ปกติ เหมือนกับการทำ setter ทั่วไป

Note : notifyDataSetChanged(); เป็นคำสั่งบอกว่ามีการอัปเดตข้อมูลใน RecyclerView โดยถ้ามีการอัปเดตข้อมูล RecyclerView จะทำการเคลียร์ข้อมูล
แล้ว refresh ทั้งหน้าใหม่และทำการแปะหน้าตาใหม่ที่ refresh ลงไปแสดงผล

MainActivity

MainActivity.java

เรียกใช้ RecyclerView และทำการ setLayoutManager ตามที่ต้องการให้เรียบร้อย โดยในตัวอย่างขอใช้เป็น LinearLayoutManager ที่แสนจะธรรมดาก็พอครับ
จากนั้นทำการเรียกใช้ adapter โดยการโยนค่า createItem() เข้าไป โดยหัวใจสำคัญอยู่ที่ createItem() นี่แหละครับ เพราะในส่วนนี้จะเป็นการเรียงลำดับการแสดงผลบนหน้าจอตามที่เราต้องการและทำการเซ็ตค่าต่างๆที่ต้องการลงไปได้เลยยย
จากนั้นกดรันเพื่อดูผลลัพธ์เลยครับ

ผลลัพธ์

ผลลัพธ์ที่ได้ก็จะออกมาหน้าตาแบบนี้ โดยสังเกตดูว่าการแสดงผลนั้นจะเรียงตามลำดับที่เราจัดไว้ใน createItem()

createItem()

แถม : ลองเปลี่ยน setLayoutManager เป็น GridLayoutManager ดูดีกว่า

GridLayoutManager

ผลลัพธ์ที่ได้

เสริมนิดหน่อย

Adapter

MainAdapter.java

ตัวอย่างนี้จะเป็น Pattern พื้นฐานสำหรับทั่วไปของ RecyclerView Adapter
อย่างแรกที่อยากให้ดูคือ extends RecyclerView.Adapter<CardViewHolder> โดยที่ทำการ extends <ViewHolder> โดยตรงจาก CardViewHolder.java
ส่วน CardViewHolder.java ก็ต้อง extends RecyclerView.ViewHolder ด้วยนะ
ซึ่งส่งผลให้ method onCreateViewHolder นั้น ต้องทำการ return View กลับไปยัง CardViewHolder.java เพียง class เดียว
ส่วนของ onBindViewHolder ก็จะได้รับค่า holder เป็นของ CardViewHolder
ซึ่งวิธีนี้เป็นการผูก MainAdapter กับ CardViewHolder.java ไว้เกินไป ถ้าหากเราจะต้องการเพิ่ม ViewHolder.java ขึ้นมาอีกสักตัวก็จะเริ่มยุ่งยากขึ้นไปอีกล่ะ

โดยส่วนตัวผมขอแนะนำการใช้ Adapter ในรูปแบบข้างต้น(ก่อนหน้านี้)
เพราะยืดหยุ่นและรองรับ ViewHolder หลายๆอันได้สะดวกกว่า

ความสามารถพิเศษของ Recycler View

สิ่งที่ผมชอบมากๆ เลยทำให้เลือกใช้ Recycler View แทน List View ไปเลย
ก็คือ การจัดตำแหน่งต่างๆของ view โดยใช้ LayoutManager เป็นตัวจัดการ หรือจะเป็น ItemDecoration คือการวาดอะไรบางอย่างให้กับ view และ ItemAnimation จัดการสร้าง Animation ได้ง่ายๆเลย

  • LayoutManager : ช่วยให้เราสามารถกำหนดตำแหน่งต่างๆของ view ได้ค่อนข้างอิสระตามใจชอบได้ง่ายๆเพียงปลายนิ้ว เช่น
    LinearLayoutManager : จัดแนวตั้งหรือแนวนอน
    GridLayoutManager : จัดวางแบบเป็นแถว
    StaggeredGridLayoutManager : จัดวางได้ค่อนข้างอิสระ(ตามรูป3–4) ด้านล่าง
LayoutManager
  • ItemDecoration : เราสามารถที่จะวาด อะไรบางอย่างรอบๆ view ได้
    เช่น สร้างกรอบให้กับ view
ItemDecoration
  • ItemAnimation : สร้าง Animation พวก Transition ได้เองตามต้องการ
    เมื่อมีการเพิ่มหรือลบ view ไปจะได้ไม่ดูแบบหายทิ้งไปแบบเฉยๆ
ItemAnimation

สรุป

สำหรับใครที่กำลังหัดใช้ Recycler View ใหม่ๆ ช่วงแรกๆอาจจะยากนิดหน่อย แต่ถ้าเข้าใจหลักการของมันแล้ว ก็จะง่ายขึ้นมาในระดับหนึ่ง เพราะตัว Recycler View
จะแบ่งแยกการทำงานแต่ละส่วนไว้ชัดเจน ทำให้การเขียนโค้ดเป็นไปใน
รูปแบบที่ดี โค้ดยืดหยุ่นใช้ในการทำงานได้หลากหลายกว่า แถมประสิทธิภาพในการทำงานก็ดีกว่า ListView อีกด้วย และส่วนตัวผมก็จะเลือกใช้งาน Recycler View แทน List View ไปเลยยย

--

--