[Android] Hướng dẫn sử dụng Butter Knife: thư viện hỗ trợ bind View và callback nhanh chóng
Ở bài này mình sẽ giới thiệu với các bạn 1 thư viện có thể phần nào giải quyết sự rườm rà của việc lập trình ứng dụng cho Android, cụ thể hơn là việc bind View và callback, đó là Butter Knife.
Ngay từ khi mới học lập trình với Android chắc hẳn các bạn đều biết đến câu lệnh “thần thánh” mà lại không thể thiếu đó chính là findViewById, thậm chí cũng chẳng có gì là phóng đại khi nói rằng bất kì project nào của Android cũng đều cần đến câu lệnh này. Nhưng đã bao giờ bạn cảm thấy nhàm chán thậm chí là mệt mỏi khi cứ phải lặp đi lặp lại 1 cái câu lệnh findViewById đó hay chưa, có thể bạn thì chưa nhưng mình thì rồi đấy. Và rồi 1 ngày đẹp trời (từ khá lâu trước đây) mình gặp được Butter Knife và mình đã nhận ra ngay đây chính là “đồng bọn” mà mình luôn tìm kiếm. Và hôm nay mình sẽ giới thiệu tới các bạn “đồng bọn” tuyệt vời này của mình.
Butter Knife là gì?
ButterKnife là một sản phẩm của Jake Wharton, một người sau khi đã phát chán với việc phải tự tay viết các câu findViewById khi lập trình Android và anh đã nảy ra ý tưởng về một API giúp giảm bớt thời gian và sự ức chế đó mỗi khi lập trình giao diện trên Android. Nói cơ bản thì khi sử dụng API này, các bạn có thể quên luôn cái method findViewById đi là vừa.
Nói thêm về Jake Wharton, anh là một lập trình viên chủ đạo của Square, bạn nào hay theo dõi những thư viện mã nguồn mở thì chắc chắn đã ít nhất 1 lần nghe đến tên công ty này, bởi Square sở hữu các thư viện nổi tiếng bậc nhất dành cho Android như Picasso, Retrofit hay Okhttp và mình nghĩ nếu có thời gian thì các bạn nên tìm hiểu thêm về các thư viện này.
Vậy sử dụng Butter Knife như thế nào?
Việc sử dụng Butter Knife cực kì đơn giản, các bạn chỉ cần thực hiện theo 3 bước sau:
Bước 1: Thêm thư viện vào file build.gradle
Rất đơn giản, các bạn thêm 2 dòng sau vào phần dependencies trong file build.gradle (Module: app), vậy là xong bước 1 rồi
implementation 'com.jakewharton:butterknife:10.0.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:10.0.0'
Bước 2: Bind target
Việc bind target là để butter knife được xem bạn định sử dụng layout nào và trong layout đó có các thành phần nào để từ đó tự động gán các field mà bạn khai báo ở bước 3 với các thành phần tương ứng trong layout. Lưu ý là bước này các bạn chỉ cần thực hiện 1 lần đối với mỗi 1 activity, fragment hay ViewHolder thôi nhé.
– Đối với Activity
Các bạn thêm dòng được đánh dấu bên dưới vào ngay dưới lời gọi hàm setContentView() trong onCreate():
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_activity);
ButterKnife.bind(this);
// TODO Use fields...
}
– Đối với Fragment
Tương tự với Activity, thì với Fragment các bạn cũng thêm dòng được đánh dấu bên dưới vào ngay sau đoạn inflate view trong onCreateView():
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fancy_fragment, container, false);
ButterKnife.bind(this, view);
// TODO Use fields...
return view;
}
– Đối với ViewHolder
Không chỉ hỗ trợ cho Activity và Fragment mà Butter Knife còn hỗ trợ đối với cả ViewHolder bằng việc sử dụng câu lệnh bind() trong hàm khởi tạo của ViewHolder như sau:
static class ViewHolder {
@BindView(R.id.title) TextView name;
@BindView(R.id.job_title) TextView jobTitle;
public ViewHolder(View view) {
ButterKnife.bind(this, view);
}
}
Bước 3: Gán view hoặc resouce
Nghe thì có vẻ giống như findViewById phải không, tuy nhiên Butter Knife có cách viết rất khác và hỗ trợ bạn trong rất nhiều tình huống khác nhau.
1. Đối với View trong layout
Butter Knife hỗ trợ bạn 1 cách rất đơn giản để có thể gán thuộc tính (field) tương ứng với view trên layout, điều này sẽ giúp bạn giảm đi được n lần lặp đi lặp lại để viết findViewById như mình đã nói đi nói lại rất nhiều lần đấy.
Để làm điều này, đơn giản lắm bạn chỉ thêm tiền tố(annotation) @BindView(id_view) vào trước khai báo của thuộc tính tương ứng với view đó. Nói thì có vẻ khó hiểu, hãy nhìn vào ví dụ sau là bạn sẽ hiểu ngay, dễ ẹc ấy mà
1 đoạn code bình thường như sau:
public class MainActivity extends AppCompatActivity {
TextView mTextView;
EditText mEditText;
Button mButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.text_view);
mEditText= (EditText ) findViewById(R.id.edit_text);
mButton= (Button ) findViewById(R.id.button);
}
}
Thì khi sử dụng Butter Knife sẽ như sau:
public class MainActivity extends AppCompatActivity {
@BindView(R.id.text_view) TextView mTextView;
@BindView(R.id.edit_text) EditText mEditText;
@BindView(R.id.button) Button mButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
}
}
Nhìn đơn giản hơn nhiều đúng không nào, nhưng không chỉ như thế đâu, trong 1 bài viết khác mình sẽ giới thiệu đến các bạn 1 plugin cho Android Studio để giúp bạn tự sinh mã bind view với Butter Knife cơ, còn trong bài viết này thì ta cứ tập trung vào các chức năng của thư viện này đi đã.
2. Đối với những Resource khác như string, drawable, color, …
Rất đơn giản, tương tự như với view, các bạn cũng có thể sử dụng các tiền tố (annotation) @BindBool, @BindColor, @BindDimen, @BindDrawable, @BindInt, @BindString, … để gán resource với field tương ứng (chỉ việc thay view bằng loại resource là ra ngay ấy mà :))
Ví dụ:
@BindString(R.string.title) String title;
@BindDrawable(R.drawable.graphic) Drawable graphic;
@BindColor(R.color.red) int red; // int or ColorStateList field
@BindDimen(R.dimen.spacer) Float spacer; // int (for pixel size) or float (for exact value) field
Bước 4: Gán listener cho các view
Không chỉ hỗ trợ các bạn trong việc gán (bind) view hay resource mà Butter Knife còn hỗ trợ các bạn trong việc gán (bind) các listener cho các view tương ứng.
Cụ thể để thiết lập onClickListener cho 1 button có id là R.id.submit ta có thể sử dụng đoạn code như sau:
@OnClick(R.id.submit)
public void submit(View view) {
// TODO submit data to server...
}
Các bạn có thể để ý thấy là ta chỉ việc thêm @OnClick(view_id) sau đó viết hàm handler sự kiện onClick là xong chứ không cần thiết phải qua từng bước getViewById, implement OnClickListener rồi setOnClickListener như trước nữa, rất tiện phải không nào.
Một lưu ý nữa là chúng ta có thể bỏ đi đối số View view truyền vào của phương thức submit() ở trên, hoặc đổi luôn thành sử dụng 1 đối tượng dạng Button làm đối số truyền vào để tiện cho việc sử dụng trong phương thức chứ không cần phải cố định là dạng View như mặc định của Android nữa.
Đến đây mình đã giới thiệu tới các bạn 4 bước chính để sử dụng Butter Knife trong project của các bạn. Mình tin rằng chỉ với việc áp dụng 4 bước trên thì các bạn đã có thể tiết kiệm được khá nhiều thời gian rồi, tuy nhiên thư viện này vẫn còn nhiều tính năng hữu ích nữa mà mình chưa giới thiệu hết ở đây, để hiểu được rõ hơn các bạn có thể truy cập vào trang chủ của Butter Knife theo link http://jakewharton.github.io/butterknife/ để tìm hiểu thêm nhé.
Cảm ơn các bạn đã đọc bài viết.
Chào thân ái và quyết thắng!
Theo dõi VnCoder trên Facebook, để cập nhật những bài viết, tin tức và khoá học mới nhất!