Android L Developer Preview - ทดลองเล่น RecyclerView
Image Cover: http://googledevelopers.blogspot.com/
หลักจากงาน Google I/O 2014 เมื่อวานนั้น Google ได้ทำการเปิดตัว Android L Developer Preview ซึ่งไอ้เจ้า Android L นั้นมันนำการออกแบบสไตล์ที่เรียกกันว่า Material Design มาใช้ หากอยากรู้เกี่ยวกับ Material Design มากขึ้น ก็ เปิดวาร์ปนี้เลยครับ
ในส่วนของ Android L Preview มันก็มีส่วน UI Widget ตัวนึงที่น่าสนใจไม่น้อย นั้นก็คือ RecyclerView แล้ว RecyclerView มันคืออะไรล่ะ? แล้วใช้ทำอะไร?
RecyclerView คืออะไร?
คำอธิบายจากเว็บไซต์เลย อธิบายว่า
The new RecyclerView widget is a more advanced version of ListView that provides performance improvements for dynamic views and is easier to use
หรือมันก็คือ ListView ฉบับปรับปรุง เพิ่มประสิทธิภาพ และใช้งานได้ง่ายขึ้นนั้นเอง หลังจากที่ลองเล่นแล้ว ก็พบว่าม้ันมีข้อดีหลายๆอย่างเลย อย่างเช่น
- มันทำ ListView ได้ทั้งแนวตั้ง แนวนอนเลย
- มี LayoutManager คอยควบคุม element
- ใช้ ViewHolder Pattern ซึ่งช่วยในเรื่องการ reuse อย่างมาก
- เหมาะสำหรับ ListView ที่ข้อมูลมีการเปลี่ยนแปลงบ่อยๆ
- มี Animation ด้วย (จริงๆ ListView แบบเก่า มันก็ทำได้เหมือนกันนะ)
จากรูปจะเห็นได้ว่า หากเราจะสร้าง RecyclerView
เราต้องมี Adapter
และ LayoutManager
ฟังดูคุ้นๆมั้ย? มันก็เหมือนกับการสร้าง ListView ธรรมดาน้นแหละ เพียงแต่ว่า เจ้า RecyclerView
นั้นมี LayoutManager
พ่วงมาด้วย คอยจัดการทุกๆอย่าง เกี่ยวกับข้อมูลใน List ให้ คอยจัดการว่า View ไหนควรจะนำกลับมาใช้ใหม่ หรือแม้แต่การหลีกเลี่ยงการใช้ findViewById
ซ้ำๆ ซึ่งมันมีผลต่อ perfomance มากๆ หากข้อมูลมีขนาดใหญ่
ข้อมูลข้างต้น ผมเพียงสรุปจากความเข้าใจ และความเห็นส่วนตัวเท่านั้น หากต้องการอ่านให้ละเอียด แนะนำอ่านจากต้นฉบับดีกว่าครับ ตามนี้เลย UI Widgets: RecyclerView
มาทดลองเล่น RecyclerView กันเลยดีกว่าครับ
เครื่องมือที่ควรมี
- Android Studio 0.8.0+ หรือ Eclipse/ADT Bundle เวอร์ชั่น 23+
- Android SDK Tools เวอร์ชั่น 23
- Android SDK Build-Tools และ Platform-Tools เวอร์ชั่น 20
- Android L (API 20) และ SDK Platform ของ Android L Preview
Create Project
เริ่มแรก ทำการสร้างโปรเจ็คขึ้นมาเลยครับ แล้วก็สร้างโปรเจ็คตามรูปเลย
เมื่อสร้างโปรเจ็คเสร็จ เราจำเป็นต้องเพิ่ม dependencies ในไฟล์ build.gradle
ของ module ครับ เปิดไฟล์ขึ้นมา เพิ่มนี้ลงไป เป็นแบบนี้
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile "com.android.support:recyclerview-v7:+"
}
จากนั้นกด Sync Project เป็นอันเรียบร้อย สามารถใช้ widget RecyclerView
ได้แล้ว ไฟล์ build.gradle
สุดท้ายจะเป็นแบบนี้
apply plugin: 'com.android.application'
android {
compileSdkVersion 'android-L'
buildToolsVersion "20.0.0"
defaultConfig {
applicationId "com.devahoy.hellorecyclerview"
minSdkVersion 15
targetSdkVersion 'L'
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile "com.android.support:recyclerview-v7:+"
}
CustomAdapter
ทำการสร้าง CustomAdapter
กันก่อน โดยต้องทำการ extends คลาส RecyclerView.Adapter
แบบนี้
package com.devahoy.hellorecyclerview;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
private List<Player> mPlayers;
private Context mContext;
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mName;
public TextView mClub;
public ViewHolder(View view) {
super(view);
mName = (TextView) view.findViewById(R.id.name);
mClub = (TextView) view.findViewById(R.id.club);
}
}
public CustomAdapter(Context context, List<Player> dataset) {
mPlayers = dataset;
mContext = context;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext)
.inflate(R.layout.recycler_view_row, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
Player player = mPlayers.get(position);
viewHolder.mName.setText(player.getName());
viewHolder.mClub.setText(player.getClub());
}
@Override
public int getItemCount() {
return mPlayers.size();
}
}
เมธอดที่สำคัญที่เราทำการ override มีด้วยกันดังนี้
onCreateViewHolder()
: สำหรับสร้าง ViewHolder ถูกเรียกโดยLayoutManager
มันเหมือนกับตอนเราสร้าง ListView แล้วใช้วิธีเช็คว่า View เป็น null หรือไม่ ถ้าเป็น ก็ให้สั่งเชื่อม/ผูก View โดยfindViewBydId()
onBindViewHolder()
: เมธอดนี้ก็ถูกเรียกโดยLayoutManager
เหมือนกัน เอาไว้สำหรับ เซทค่า dataset ของเรา ใส่ไปยังพวก View ต่างๆ เช่นใส่ค่าให้ TextView, ImageViewgetItemCount()
: ส่งค่าจำนวน item ของ dataset
จากเมธอด ด้านบน เราจะเห็นว่า มันเหมือนการใช้ ViewHolder Pattern แบบที่เราเคยทำเลย โดยที่เราไม่ต้องมาเช็คว่า View มันเป็น null รึเปล่า เราแค่ เชื่ิอม View กับ View ใน xml ในเมธอด onCreateViewHolder()
และเซทค่า content ใน onBindViewHolder()
ก็พอ
โค๊ดด้านบน ปล่อยให้ error ก่อนเนื่องจากเรายังไม่มีคลาส
Player
และเลเอาท์ชื่อrecycler_view.xml
สร้างโมเดล Player
ขั้นตอนนี้ ผมต้องการให้แสดงชื่อนักฟุตบอล และสโมสรที่สังกัด เพราะฉะนั้น ก็เลยสร้าง class ง่ายๆแบบนี้
package com.devahoy.hellorecyclerview;
public class Player {
private String name;
private String club;
public Player(String name, String club) {
this.name = name;
this.club = club;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClub() {
return club;
}
public void setClub(String club) {
this.club = club;
}
}
ส่วนไฟล์ recycler_view_row.xml
ก็ไม่มีอะไรมาก มีแค่ TextView 2 อัน ไฟล์ก็จะเป็นแบบนี้
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/name"
android:textColor="#ffee1789"
android:layout_marginRight="48dp" />
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff0071ff"
android:id="@+id/club" />
</LinearLayout>
MyActivity
ต่อมา มาที่คลาส MyActivity
ที่ส่วน onCreate()
ก็ทำแบบนี้เลย
public class MyActivity extends Activity {
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new CustomAdapter(this, initPlayer());
mRecyclerView.setAdapter(mAdapter);
}
}
จากด้านบน คือ ผูก RecyclerView
กับ id ในไฟล์ activity_my.xml
(ยังไม่ได้สร้าง) แล้วก็ทำการสร้าง LayoutManager
ขึ้นมาใหม่ จากนั้น setAdapter
โดยใช้ CustomAdapter
ที่เราได้สร้างก่อนหน้านี้แล้ว
ต่อมาเพิ่มเมธอด initPlayer()
อันนี้เอาไว้สร้างข้อมูลขึ้นมา ตรงนี้ขี้เกียจพิมพ์ ก็เลยใส่ไป 4-5 items
private List<Player> initPlayer() {
Player messi = new Player("Leonel Missi", "Barcelona");
Player ronaldo = new Player("Cristiano Ronaldo", "Real Madrid");
Player suarez = new Player("Luis Suarez", "Liverpool");
List<Player> dataset = new ArrayList<Player>();
dataset.add(messi);
dataset.add(ronaldo);
dataset.add(suarez);
return dataset;
}
สุดท้ายสร้างไฟล์ activity_my.xml
โดยใช้ widget ชื่อ android.support.v7.widget.RecyclerView
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MyActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
ทดสอบรันโปรแกรมดูครับ (AVD ต้องสร้างด้วย Android L นะครับ ใครสร้างไม่เป็น ก็นี้เลย Setup SDK )
อ้อ ตัว
RecyclerView
มันรองรับ Support Library ด้วยนะ ผมยังไม่ได้เทสเท่าไหร่ หากใครเทสหรือลองเล่นแล้ว ก็มาแชร์กันได้นะครับ
สรุป
RecyclerView
ส่วนตัวคิดว่า มันก็น่าสนใจดีครับ ตามสไตล์ของ Material Design ต้องรอดูต่อไปว่า อนาคตมันจะเป็นเช่นไร เนื่องจากตอนนี้ยังไม่มีข้อมูลอะไรมาก รายละเอียดก็น้อย บางทีก็บัคกระจายเลย สำหรับใครสนใจเพิ่มเติม ก็ลองไปอ่านต้นฉบับดู น่าจะรู้เรื่องกว่าอ่านที่นี่นะครับ :D
- Authors
- Name
- Chai Phonbopit
- Website
- @Phonbopit