หากจะหา view ใน XML แล้วหละก็ เพื่อนๆ นักพัฒนา Android ก็คงจะนึกถึง findViewById กันเป็นอันดับแรก ซึ่งวันนี้ผมมีของดีมานำเสนออีกแล้วครับ ของดีที่ว่านั้นก็ คือ คือ คืออออออ Butter Knife นั่นเอง ส่วนความสามารถของ library ตัวนี้จะมีอะไรบ้าง ก็ต้องตามมาอ่านดูในบทความนะครับ
วิธีดั้งเดิมใช้มาตั้งแต่สมัยบรรพบุรุษ ด้วย findViewById
พอเห็นความต่างไหมใช่ไหมครับ แล้วลองนึกภาพที่เรามี View เยอะๆ โค้ดแบบเดิมจะยาวกว่าซึ่งถ้าเราเปลี่ยนมาใช้ Butter Knife จะเห็นว่าโค้ดจะดูสะอาดตาขึ้น นอกจากนี้ยังลดความผิดพลาดเรื่องการ casting type ของ view ได้อีกด้วย
สรุปแล้วโดยส่วนตัวผมค่อนข้างชอบ Butter Knife นะครับ เพราะใช้แล้วรู้สึกว่าโค้ดดูสะอาดขึ้นมาอีกนิดนึง แล้วก็ยังช่วยตัดปัญหาเรื่อง casting type ของ view ไปได้อีกหน่อยนึง สำหรับใครที่ยังไม่ได้ลองว่างๆ ก็ลองหาโอกาสเล่นดูนะครับ
(อ้างอิงจาก : github.com)
ขอบคุณ คุณเอกสุดหล่อ ที่แจ้งเข้ามานะครับ
Update : Butter Knife มีการ update version จาก 6.x.x ไปเป็น 7.x.x ซึ่งมีการเปลี่ยน API บางส่วน เลยขออนุญาตแก้ไขบทความนะครับ
การเปลี่ยนแปลงหลักๆ จาก 6.x.x ไป 7.x.x
@InjectView(View ID) -> @Bind(View ID)
ButterKnife.inject(this); -> ButterKnife.bind(this);
ดู Change log เพิ่มเติม ที่นี่
การติดตั้ง
ก็เช่นเคย ที่ build.gradle ครับcompile 'com.jakewharton:butterknife:7.0.1'
การใช้งานเบื้องต้น
เพื่อให้เห็นภาพ เรามาดูการเปรียบเทียบกับวิธีการแบบเดิมกันก่อนดีกว่าวิธีดั้งเดิมใช้มาตั้งแต่สมัยบรรพบุรุษ ด้วย findViewById
class ExampleActivity extends Activity {
private Button myButton;
private TextView myTextView1;
private TextView myTextView2;
private TextView myTextView3;
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);
myButton = (Button) findViewById(R.id.my_button);
myTextView1 = (TextView) findViewById(R.id.my_textview1);
myTextView2 = (TextView) findViewById(R.id.my_textview2);
myTextView3 = (TextView) findViewById(R.id.my_textview3);
}
}
ต่อไปมาดูของ Butter Knife ด้วย annotation @Bindclass ExampleActivity extends Activity {
@Bind(R.id.my_button) Button myButton;
@Bind(R.id.my_textview1) TextView myTextView1;
@Bind(R.id.my_textview2) TextView myTextView2;
@Bind(R.id.my_textview3) TextView myTextView3;
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);
ButterKnife.bind(this); // บรรทัดต้องใส่ทุกครั้ง เพื่อเป็นการเริ่มการทำงานของ Butter Knife
}
}
จากโค้ดทั้ง 2 ชุดด้านบนมีการทำงานเหมือนกัน คือ หา view ด้วย ID ใน res/layout/my_layout.xml นั่นเองพอเห็นความต่างไหมใช่ไหมครับ แล้วลองนึกภาพที่เรามี View เยอะๆ โค้ดแบบเดิมจะยาวกว่าซึ่งถ้าเราเปลี่ยนมาใช้ Butter Knife จะเห็นว่าโค้ดจะดูสะอาดตาขึ้น นอกจากนี้ยังลดความผิดพลาดเรื่องการ casting type ของ view ได้อีกด้วย
ใช้กับ Fragment ได้ด้วยนะ
public class ExampleFragment extends Fragment {
@Bind(R.id.button1) Button button1;
@Bind(R.id.button2) Button button2;
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.my_fragment, container, false);
ButterKnife.bind(this, view);
return view;
}
}
ตรงนี้สังเกตุว่า parameter จะเปลี่ยนไปเล็กน้อยจากการใช้งานใน Activity นะครับ
Activity : ButterKnife.bind(this);
Fragment : ButterKnife.bind(this, view);
ยังไม่พอใช้กับ Adapter ก็ยังได้!!
public class MyAdapter extends BaseAdapter {
@Override public View getView(int position, View view, ViewGroup parent) {
ViewHolder holder;
if (view != null) {
holder = (ViewHolder) view.getTag();
} else {
view = inflater.inflate(R.layout.whatever, parent, false);
holder = new ViewHolder(view);
view.setTag(holder);
}
holder.name.setText("John Doe");
// etc...
return view;
}
static class ViewHolder {
@Bind(R.id.title) TextView name;
@Bind(R.id.job_title) TextView jobTitle;
public ViewHolder(View view) {
ButterKnife.bind(this, view);
}
}
}
เล่นกับ Event ก็ยังได้
@OnClick@OnClick(R.id.submit)
public void submit(View view) {
...
}
@OnCheckedChange
@OnCheckedChange(R.id.radio)
public void checkedChanged(boolean checked) {
...
}
การใช้งานทั่วๆ ไปก็จะใช้งานประมาณนี้ แต่ก็ยังมีความสามารถอื่นๆ โดยสามารถเข้าไปดูได้ที่ลิงค์อ้างอิงเพิ่มเติมได้เลยครับสรุปแล้วโดยส่วนตัวผมค่อนข้างชอบ Butter Knife นะครับ เพราะใช้แล้วรู้สึกว่าโค้ดดูสะอาดขึ้นมาอีกนิดนึง แล้วก็ยังช่วยตัดปัญหาเรื่อง casting type ของ view ไปได้อีกหน่อยนึง สำหรับใครที่ยังไม่ได้ลองว่างๆ ก็ลองหาโอกาสเล่นดูนะครับ
"ไม่ต้องเชื่อผมก็ได้ แต่ผมอยากให้คุณเปิดใจ :)"
ข้อพึงระวัง
หากโปรเจคมีการแยก Module ออกมาหลายๆ Module จะสามารถเรียกใช้งาน Butter Knife ได้บน Main Module เท่านั้น เนื่องจากเป็นข้อจำกัดของ Java's annotations และ Android SDK.(อ้างอิงจาก : github.com)
ขอบคุณ คุณเอกสุดหล่อ ที่แจ้งเข้ามานะครับ
ลิงค์อ้างอิง
View injection library : Butter Knife