androidServerlogo
اتصال اندروید به وب سرور با Restful API با استفاده از Asp.net و Retrofit
آبان ۱, ۱۳۹۶
butterknife-logoplugin
نصب پلاگین کتابخانه ButterKnife در اندروید استودیو
آبان ۷, ۱۳۹۶

همه چیز درباره کتابخانه ButterKnife در اندروید

butterknife-logo

butterknife-logo

کتابخانه ButterKnife ناجی و فرشته ی نجات برنامه نویسان اندروید برای خلاص شدن از نوشتن متدهای طولانی findViewByID , onClick , onItemClick و مقداردهی یا initialize متفیر های مختلف و بسیاری از کدهای دیگر که تنها وظیفه پر کردن و کثیف کردن کلاس مارو داشت.

همه چیز درباره کتابخانه ButterKnife دراندروید

به عبارتی کتابخانه ButterKnife امکانات زیر را برای کاربر فراهم کرده

  1.  استفاده از انوتیشن annotation) @BindeView به جای findViewByID)
  2. گروه بندی چندین view در یک ارایه یا لیست و اعمال عملیاتی برروی همه آنها به صورت یکجا و با یک بار کدنویس با actions, setter , properties
  3. استفاده از انوتیشن های مثل @onClick به جای کلاس های listener
  4. استفاده از انوتیشن هایی مثل @BindBitmap برای مقداردهی به فیلدها
  5. استفاده از UnBinder در فرگمنت ها برای آزاد سازی فضایی که به view های فرگمنت اختصاص داده شده بود .

برای استفاده از این کتابخانه مشخصا باید اول بریم سراغ گردل برنامه و با ButterKnife آشناش کنیم پس دو خط زیر رو به dependencies اضافه میکنیم

// butter knife
compile 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'

بعد از sync کردن پروژه میتونیم از تمامی انوتیشن های این کتابخانه استفاده کنیم اما نکته مهم این که بعد از استفاده از این انوتیشن ها باید در onCreate اکتیویتی یا فرگمنت حتما خط زیر رو اضافه کنیم تا bind ها به درستی اعمال بشن

// bind the view using butterknife
ButterKnife.bind(this);

-View Binding

۱-BindView@

پرکاربرد ترین انوتیشن این کتابخانه , انوتیشنی ست که بجای دستور ()findViewById استفاده میکنیم یعنی @BindView.
خب مشخصه که چکاری رو برای ما انجام میده ! حالا دیگه تنها کافیه به جای تعریف view و بعد مقدار دهی اون با استفاده از cast کردن به نوع view درخواستی و بعد هم اشاره کردن به id با استفاده از findViewById فقط بنویسیم

@BindView(R.id.nameTextView)
TextView mNameTextView;
@BindView(R.id.nameEditText)
EditText mNameEditText;

@BindView(R.id.button)
Button mbutton1;

یا هر view دیگه ای که در فایلxml خود دارید و در نهایت هم در متد onCreate برنامه دستور bind رو بدین صورت حتما ذکر کنید

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// bind the view using butterknife
ButterKnife.bind(this);
}

۲-BindViews@

لیستی از view ها را bind میکند

@BindViews({R.id.lbl_name, R.id.lbl_email, R.id.lbl_address})
List<TextView> lblArray;

-Resource Binding

بخش دیگری از انوتیشن های ما داخل ButterKnife برای اختصاص دادن منبع یا مقداری به فیلدهاست که در ادامه باهاشون آشنا میشیم !

۱- BindArray@

مشخصا برای اختصاص یک ارایه به فیلد بکار میرود برای مثال یک ارایه در فایل strings پروژه ایجاد کنید

<resources>
<string-array name="programmingLang">
<item>android</item>
<item>c</item>
<item>java</item>
<item>js</item>
<item>php</item>
<item>go</item>
</string-array>
</resources>

و در اکتیویتی خود اینطور عمل کنید

@BindArray(R.array.programmingLang) String[] progLang;

فراموش نکنید که حتما داخل متد onCreate هم دستور (ButterKnife.bind(this رو بنویسید .

این انوتیشن رو همچنین میتونید برای آرایه های دیگه ازجنس int ,TypedArray ,CharSequnce هم بکار ببرید.

۲-BindBitmap@

برای اختصاص دادن یک فایل از شاخه drawable به یک فیلد به راحتی زیر

@BindBitmap(R.mipmap.ic_launcher) Bitmap launcherBitmap;

اما نکته قابل توجه درباره این انوتیشن این است که به شما تصویر با سایز اصلی را برمیگرداند بدون کوچک کردن یا تغییر سایز بنابراین شما خود باید تصویر را به صورتی دستی و یا با استفاده از کتابخانه های glide  یا پیکاسو    تغییر سایز دهید و ا ستفاده کنید تا با اخطار هایی مثل OutOfMemoryException مواجه نشوید.

۳-BindDrawable@

برای bindکردن المان های drawable

@BindDrawable(R.mipmap.ic_launcher)
Drawable drawableLogo;

۴-BindString@

برای bind کردن یک مقدار string

@BindString(R.string.app_name)
String appName;

۵-BindColor@

برای bindکردن مقدار color

@BindColor(R.color.colorPrimaryDark)
int colorTitle;

۶-BindDimen@

برای bind کردن مقدار dimen یا اندازه

@BindDimen(R.id.padding_hori)
float paddingHorizontal;

۷-BindAnim@

مقدار animation را bind میکند

;BindAnim(R.anim.move_up)
Animation animMoveUp;

۸-BindFont@

مقدار font را اختصاص میدهدمقدار font را اختصاص میدهد

@BindFont(value = "test.ttf", bold = true)
 @BindView(R.id.label) TextView label;

۹-BindFloat@

مقدار float را bind میکند

@BindFloat(R.dimen.radius)
float radius;

۱۰-BindInt@

مقدار int را bind میکند

@BindInt(R.integer.distance)
int distance;

-Listener Bindings

قطعا با listener ها آشنا هستید ! قبلا برای انجام عملیاتی خاص در حالتی خاص از view باید از listener ها به صورت زیر استفاده میکردیم

Button mbutton2;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mbutton2=(Button) findViewById(R.id.button2);
mbutton2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG,"button has clicked");
}
});
}

خب میبینید که ما ۶ خط کد صرفا برای onClick برنامه نوشتیم خب فکر کنید بخوایم برای چندین view این listener ها رو صدا بزنیم !!!
اینجا است که ButterKnife قدرت خودشو نشون میده

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// bind the view using butterknife
ButterKnife.bind(this);
}

@OnClick(R.id.button)
void onButtonClick(){
Log.e(TAG,"button has clicked");
}

خب میبیند که

  1. هیچ فیلد یا variable ی برای button تعریف نشده
  2. انوتیشن @onClick به شناسه یا ID view که listener برای آن در نظر گرفته شده اشاره میکند
  3. متد annonated شده و حتی نیاز به ذکر سطوح دسترسی هم ندارد (مثل یک فیلد)
  4. نام متد نیز به دلخواه شماست و مهم نیست که چه نامی بگذارید
  5. اگر توجه کنید در نوشتن listenerها به صورت سنتی و override کردن ما حتما یک پارامتر View داشتیم این درحالی است که این پارامتر ها در ButterKnife کاملا اختیار یا Optional است

انوتیشن های listener موجود در ButterKnife

  1. OnCheckedChange@
  2. -OnClick@
  3. OnEditorAction@
  4. OnFocusChange@
  5. OnItemLongClick@
  6. OnItemClick@
  7. OnTouch@
  8. OnLongClick@

Binding Multiple Views

ما در اندروید به کررات با این صحنه مواجه شده ایم که یک listener را برای چندین view درظر بگیریم ازجمله کلیک برروی buttonها
خبر خوب این است که butterKnife این کاررو هم برای ما راحت کرده بدین صورت

@OnClick({
R.id.redImageButton,
R.id.amberImageButton,
R.id.greenImageButton
})
void onLightClicked(ImageButton lightButton) {
switch(lightButton.getId()) {
case R.id.redImageButton:
// Turn on red light
break;

case R.id.amberImageButton:
// Turn on amber light
break;

case R.id.greenImageButton:
// Turn on green light
break;
}
}

خب نکات طلایی این قسمت

  • تمامی انوتیشن های Butter Knife ارایه ای از ID هارا جهت اعمال عملیات برروی همه آنهابه صورت یکجا, قبول میکنند
  • همانطور که قبلاهم گفتیم پارامتر های متدهای Butter Knife کاملا optional هستند که ما اینجا از ImageButton استفاده کردیم و اگر عمیق تر توجه کرده باشید هنگام override کردن listener ها ما فقط پارامتر view رو داشتیم ! درحالی که با این کتابخانه دست ما در انتخاب پارامتر باز هست چون Butter Knife زحمت Type Casting رو برای ما میکشه!

Multi-Method Listeners

ما در اندروید listener هایی هم داریم که interface آنها بش از یک متد دارد مثل TextWatcher

textView.addTextChangedListener(
new TextWatcher() {

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// No-op
}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// No-op
}

@Override
public void afterTextChanged(Editable s) {
validateEmail(s);
}
});

این درحالی است که بیشتر اوقات ما با تمامی متدهای interface کاری نداریم و عملیات مدنظر ما در یکی از متدها هم قابل اعمال است.
پس باز هم میریم سراغ Butter Knife و معجزه های که میکنه!

@OnTextChanged(value = R.id.emailEditText,
callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
void afterEmailInput(Editable editable) {
validateEmail(editable);
}

انوتیشن onTextChanged مثل بقیه انوتیشن هاست و میتواند آرایه ای از view هارا با استفاده از شناسه آنها دریافت کند اما اینجا ما تنها یک شناسه به عنوان value و یک Callback که درواقع همان متد interfaceی است که مدنظر ماست که میخواهیم این انوتیشن برروی آن اعمال شود.
Butter Knife دارای ۳ انوتیشن multi-method میباشد

  1. OnItemSelected@
  2. OnPageChange@
  3. OnTextChanged@

Dynamic Views and Listener Bindings

اگر شما انوتیشن listenerی را bind یا به اصطلاح الحاق کردید که ممکن است گاهی وجود نداشته باشد میتوانید از انوتیشن @Optional استفاده کنید

@OnClick(R.id.proposeIfSingleButton)
@Optional
void proposeIfSingle() {
// On your knees pal (wink)
}

این دقیقا مشابه روشی است که ما از انوتیشن @Nullable برای viewهایی استفاده میکنیم که ممکن است گاهی موجود نباشند.
Custom View Listeners
همچنین در CustomView هایی که میسازید میتونید از listenerهای ButterKnife استفاده کنید اما دیگر نیاز به دادن ID نیست

public class TwitterFavoriteButton
 extends Button {

@OnClick
void favoriteTweet() {
// Favorite the damn tweet...
}
}

View Lists, Actions ,Setters and Properties

View Lists

ممکن است زمانی بخواهیم عملیاتی برروی دسته ای از View ها انجام دهیم همانطور که قبلا هم گفتیم ما در تمامی انوتیشن های Butter Knife میتوانیم آرایه

یا لیستی از view هارا داشته باشیم اما برای بدست آوردن لیستی از view ها در یک فیلد باید از @BindViews استفاده کنیم.

public class PickAvengersActivity extends Activity {

@BindViews({
R.id.ironMan, R.id.captainAmerica,
R.id.thor, R.id.blackWidow,
R.id.hawkeye, R.id.hulk
})
CheckBox[] avengers;

// ...
}

خب حالا ما لیستی از view ها رو داریم حالا باید راهی برای اعمال عملیاتی برروی همه آنها به صورت یکجا پیدا کنیم که Butter Knife فکر اینجا هم کرده در ادامه با actions , setters ,properties که تمامی کارهارو برای ما میکنند آشنا میشیم.

Actions

ما در بالا لیستی از چک باکس هارو درون فیلدی به عنوان avengers قرار دادیم حالا میخواهیم با استفاده از action تمامی view های داخل این لیست رو تیک بزنیم پس

public class PickAvengersActivity
 extends Activity {

@BindViews({
R.id.ironMan, R.id.captainAmerica,
R.id.thor, R.id.blackWidow,
R.id.hawkeye, R.id.hulk
})
CheckBox[] avengers;

final Action<CheckBox> SELECT_ALL = new Action<>() {
@Override
public void apply(@NonNull CheckBox checkBox, int index) {
checkBox.setChecked(true);
}
};

// ...

@OnClick(R.id.selectAllButton)
void selectAll() {
ButterKnife.apply(avengers, SELECT_ALL);
}
}

خب مشخصا ما یک instance یا نمونه جدید از Action ایجاد کردیم که دارای متد apply برای اعمال عملیات مدنظر ما برروی تمامی اجزا لیست با استفاده از index است.
و با استفاده از انوتیشن @onClick اشاره شده که با فشردن یک کلید لیستی از ویو هارا به Actionی تحت عنوان SELECT_ALL برای اعمال عملیاتی خاص ارسال کند.

Setters

خب حال اگر بخواهیم برای مثال یک کلید دیگر تحت عنوان Clear برای unCheck کردن تمامی چک باکس ها در فایل xml خود قرار دهیم تا چک باکس هارا از حالت انتخاب خارج کند خب میتوانیم Action دیگری بنویسیم برای این عملیات اما راه حل دیگری نیز وجود دارد و آن استفاده از setter است.
حال setter چیست؟ خب به ساده ترین حالت ممکن میتون گفت setter ها دقیقا مشابه Action ها هستند با این تفاوت که اجازه ارسال یک مقدار اضافه بر پارامتر های قبلی را به شما میدهد تا بتوانید عملیات منعطف تری اعمال کرد برای مثال میتوان مثال فوق را بدین صورت تغییر داد

public class PickAvengersActivity
 extends Activity {

@BindViews({
R.id.ironMan, R.id.captainAmerica,
R.id.thor, R.id.blackWidow,
R.id.hawkeye, R.id.hulk
})
CheckBox[] avengers;

final Setter<CheckBox, Boolean> CHECKED = new Setter<>() {
@Override
public void set(@NonNull CheckBox view, Boolean value, int index) {
checkBox.setChecked(value != null ? value : false);
}
};

// ...

@OnClick(R.id.selectAllButton)
void selectAll() {
ButterKnife.apply(avengers, CHECKED, true);
}

@OnClick(R.id.clearButton)
void clear() {
ButterKnife.apply(avengers, CHECKED, false);
}

}

خب همانطور که مشاهده میکنید ساختار setter شبیه به action است تنها تفاوت آن پارامترهای متد apply است و متدهای onClick کلید ها که براساس کلید انتخابی مقدار value مناسبی ارسال میشود.

properties

آخرین آپشن نیز property ها هستند که میتوان آنهارا بروی view ها اعمال کرد

  1. ALPHA
  2. TRANSLATION_X
  3. TRANSLATION_Y
  4. TRANSLATION_Z
  5. X
  6. Y
  7. Z
  8. ROTATION
  9. ROTATION_X
  10. ROTATION_Y
  11. SCALE_X
  12. SCALE_Y

طریقه اعمال آنها نیز با متد apply به صورت زیر است

@OnClick(R.id.fade50Button)
void fade50() {
ButterKnife.apply(translucentViews, View.ALPHA, 0.5f);
}

برای نصب پلاگین کتابخانه ButterKnife به پست بعدی ما مراجعه کنید 🙂

 

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *