日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

android ButterKnife的简单使用

發(fā)布時(shí)間:2024/4/15 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android ButterKnife的简单使用 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

今天,簡(jiǎn)單講講android里如何使用ButterKnife。

Android框架系列:

一.android EventBus的簡(jiǎn)單使用

二.android Glide簡(jiǎn)單使用

三.android OKHttp的基本使用詳解

四.android RxJava(RxAndroid)的簡(jiǎn)單使用

五.android ButterKnife的簡(jiǎn)單使用

?

前言:
ButterKnife是一個(gè)專注于Android系統(tǒng)的View注入框架,以前總是要寫很多findViewById來找到View對(duì)象,有了ButterKnife可以很輕松的省去這些步驟。是大神JakeWharton的力作,目前使用很廣。最重要的一點(diǎn),使用ButterKnife對(duì)性能基本沒有損失,因?yàn)锽utterKnife用到的注解并不是在運(yùn)行時(shí)反射的,而是在編譯的時(shí)候生成新的class。項(xiàng)目集成起來也是特別方便,使用起來也是特別簡(jiǎn)單。

?

ButterKnife 閃亮登場(chǎng)

ButterKnife 初識(shí)

ButterKnife,又被戲稱為黃油刀,至于為什么被戲稱為這個(gè),大家可以看下面附上的從官方截取的icon~

一塊桌布,一個(gè)盤子,一個(gè)Android小機(jī)器人形狀的黃油,一把刀。這些合起來被大家戲稱為黃油刀。(我說呢,糾結(jié)我半天,都搞不懂黃油刀是個(gè)什么鬼,這次曉得了)

icon下面簡(jiǎn)單解釋就是為Android 視圖(View)提供綁定字段和方法。 也就是說,我們今后可以通過這把刀去替換之前瑣碎的初始化~

?

一、 ButterKnife是啥

注解中相對(duì)簡(jiǎn)單易懂的很不錯(cuò)的開源框架
1. 強(qiáng)大的View綁定和Click事件處理功能,簡(jiǎn)化代碼,提升開發(fā)效率
2. 方便的處理Adaper里的ViewHolder綁定問題
3. 運(yùn)行時(shí)不會(huì)影響app效率,使用配置方便
4. 代碼清晰,可讀性強(qiáng)

github開源地址:
https://github.com/JakeWharton/butterknife

?

?

二、使用步驟

2.1 添加插件

File -> Settings -> Plugins -> 搜索ButterKnife,找到Android ButterKnife Zeleany進(jìn)行安裝重啟AndroidStudio

?

2.2 添加依賴

在對(duì)應(yīng)module的build.gradle里面添加下面的依賴,重新編譯就會(huì)自動(dòng)下載

dependencies {compile 'com.jakewharton:butterknife:8.5.1'annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1' }

注意和Dagger2配合使用需要注意把a(bǔ)nnotationProcessor改為apt。

2.3 在Activity中使用

2.3.1 使用插件

在R.layout.activity_main上面右擊 選擇Generate -> Generate ButterKnife injections,即可選擇 生成view對(duì)應(yīng)的注解,還支持ViewHolder和OnClick

2.3.2 手動(dòng)

  • 綁定ButterKnife
  • @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//綁定初始化ButterKnifeButterKnife.bind(this); }
  • 定義View
  • 下面的代碼把R.id.tv_test這個(gè)TextView定義了為tvTest,注意類型不能為static或者private

    @BindView(R.id.tv_test) TextView tvTest;//當(dāng)然寫成一行也是可以 @BindView(R.id.tv_test) TextView tvTest;
  • 點(diǎn)擊事件
  • 添加注解@OnClick(R.id.xx)即為點(diǎn)擊方法,對(duì)應(yīng)的View參數(shù)可有可無(wú),如果有多個(gè)參數(shù)可以只加一個(gè)參數(shù)(例如onItemClick有四個(gè)參數(shù),你可以只加一個(gè)int position的參數(shù))。如果參數(shù)錯(cuò)誤,編譯的時(shí)候會(huì)報(bào)錯(cuò)。

    @OnClick(R.id.bt_test) public void onClick(View v) {tvTest.setText("被點(diǎn)擊了..."); }

    如果定義為指定的類型,將會(huì)自動(dòng)轉(zhuǎn)換

    @OnClick(R.id.bt_test) public void onClick(Button button) {tvTest.setText("被點(diǎn)擊了..."); }

    更多事件看下面的 三

    2.4 在Fragment中使用

    在Fragment中使用和在Activity中使用,只是有一點(diǎn)不一樣:在獲取View的時(shí)候,加多一個(gè)view參數(shù)把View綁定到ButterKnife就行了。

    @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.my_fragment, container, false);//這里需要加多一個(gè)參數(shù)viewButterKnife.bind(this, view);return view; }

    Fragment生命周期和activity有點(diǎn)不同,銷毀的時(shí)候可以進(jìn)行解綁

    public class MyFragment extends Fragment {@BindView(R.id.bt_test)Button btTest;private Unbinder unbinder;@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.my_fragment, container, false);//綁定的時(shí)候返回了一個(gè)Unbinder對(duì)象unbinder = ButterKnife.bind(this, view);return view;}@Overridepublic void onDestroyView() {super.onDestroyView();unbinder.unbind();} }

    2.5 在Adapter ViewHolder中使用

    把ViewHolder加一個(gè)構(gòu)造方法,在new ViewHolder的時(shí)候把view傳遞進(jìn)去。

    static class ViewHolder {@BindView(R.id.tv_item_test)TextView tvItemTest;@BindView(R.id.bt_item_test)Button btItemTest;public ViewHolder(View view) {ButterKnife.bind(this, view);} }

    item里面Button控件的點(diǎn)擊事件也可以使用注解@OnClick來實(shí)現(xiàn),在適配器里面添加就行,如:

    //item的button的點(diǎn)擊事件@OnClick(R.id.bt_item_test)void onClick(){Toast.makeText(context,"點(diǎn)擊了按鈕",Toast.LENGTH_SHORT).show();}static class ViewHolder {@BindView(R.id.tv_item_test)TextView tvItemTest;@BindView(R.id.bt_item_test)Button btItemTest;public ViewHolder(View view) {ButterKnife.bind(this, view);}}

    注意: 如果item里面有Button等這些有點(diǎn)擊的控件事件的,需要設(shè)置這些控件屬性focusable為false

    三、 事件注解

    一共有12個(gè)

    名稱作用
    @OnClick點(diǎn)擊事件
    @OnCheckedChanged選中,取消選中
    @OnEditorAction軟鍵盤的功能鍵
    @OnFocusChange焦點(diǎn)改變
    @OnItemClickitem被點(diǎn)擊(注意這里有坑,如果item里面有Button等這些有點(diǎn)擊的控件事件的,需要設(shè)置這些控件屬性focusable為false)
    @OnItemLongClickitem長(zhǎng)按(返回真可以攔截onItemClick)
    @OnItemSelecteditem被選擇事件
    @OnLongClick長(zhǎng)按事件
    @OnPageChange頁(yè)面改變事件
    @OnTextChangedEditText里面的文本變化事件
    @OnTouch觸摸事件
    @Optional選擇性注入,如果當(dāng)前對(duì)象不存在,就會(huì)拋出一個(gè)異常,為了壓制這個(gè)異常,可以在變量或者方法上加入一下注解,讓注入變成選擇性的,如果目標(biāo)View存在,則注入, 不存在,則什么事情都不做=如下代碼
    @Optional @OnCheckedChanged(R.id.cb_test) public void onCheckedChanged(CompoundButton buttonView,boolean isChecked){if(isChecked){tvTest.setText("被選中了...");}else{tvTest.setText("被取消了...");} }

    ?

    三、綁定注解

    有11種

    名稱解析
    @BindViews綁定多個(gè)view id為一個(gè)view的list變量
    @BindView綁定一個(gè)view id為一個(gè)view 變量
    @BindArray綁定string里面array數(shù)組,@BindArray(R.array.city ) String[] citys ;
    @BindBitmap綁定圖片資源為Bitmap,@BindBitmap( R.mipmap.wifi ) Bitmap bitmap;
    @BindBool綁定真假boolean
    @BindColor綁定color,@BindColor(R.color.colorAccent) int black;
    @BindDimen綁定Dimen,@BindDimen(R.dimen.borth_width) int mBorderWidth;
    @BindDrawable綁定Drawable,@BindDrawable(R.drawable.test_pic) Drawable mTestPic;
    @BindFloat綁定float
    @BindInt綁定int
    @BindString綁定一個(gè)String id為一個(gè)String變量,@BindString( R.string.app_name ) String meg;

    ?

    五、 ButterKnife更多使用

    4.1 指定多個(gè)id綁定事件

    例如綁定多個(gè)Button的onclick事件,在小括號(hào)里面加大括號(hào),然后用逗號(hào)分割即可。

    @OnClick({R.id.bt_test,R.id.bt_test_two})public void onClick(View v) {switch (v.getId()){case R.id.bt_test:tvTest.setText("按鈕1被點(diǎn)擊了...");break;case R.id.bt_test_two:tvTest.setText("按鈕2被點(diǎn)擊了...");break;}}

    4.2 多個(gè)view

    使用BindViews綁定多個(gè)

    @BindViews({R.id.tv_test,R.id.tv_test_two,R.id.tv_test_three}) List<TextView> tvList;

    使用Action接口或者Setter接口或者View的Property,可以同時(shí)設(shè)置多個(gè)view的屬性

    @BindViews({R.id.tv_test,R.id.tv_test_two,R.id.tv_test_three}) List<TextView> tvList;@Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ButterKnife.bind(this);//設(shè)置多個(gè)view的屬性//方式1 傳遞值ButterKnife.apply(tvList,ENABLED,false);//方式2 指定值ButterKnife.apply(tvList,DISABLE);//方式3 設(shè)置View的PropertyButterKnife.apply(tvList, View.ALPHA, 0.0f);}//Action接口設(shè)置屬性 static final ButterKnife.Action<View> DISABLE = new ButterKnife.Action<View>() {@Override public void apply(View view, int index) {view.setEnabled(false);} };//Setter接口設(shè)置屬性 static final ButterKnife.Setter<View, Boolean> ENABLED = new ButterKnife.Setter<View, Boolean>() {@Override public void set(View view, Boolean value, int index) {view.setEnabled(value);} };

    4.3 自定義View使用注解事件

    不用指定id,直接注解OnClick

    public class MyButton extends Button {@OnClickpublic void onClick() {} }

    4.4 綁定api

  • 使用Activity為根視圖綁定任意對(duì)象時(shí),如果你使用類似MVC的設(shè)計(jì)模式你可以在Activity 調(diào)用ButterKnife.bind(this, activity),來綁定Controller。

  • 使用ButterKnife.bind(this)綁定一個(gè)view的子節(jié)點(diǎn)字段.如果你在子View的布局里或者自定義view的構(gòu)造方法里 使用了inflate,你可以立刻調(diào)用此方法。或者,從XML inflate來的自定義view類型可以在onFinishInflate回調(diào)方法中使用它。

  • 4.5 多方法的listener

    例如Spinner的setOnItemSelectedListener,他會(huì)回調(diào)兩個(gè)方法:

    mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {@Overridepublic void onItemSelected(AdapterView<?> parent, View view, int position, long id) {}@Overridepublic void onNothingSelected(AdapterView<?> parent) {} });

    所以這時(shí)候如果我們需要注解onNothingSelected,需要在注解參數(shù)添加一個(gè)callback

    @OnItemSelected(R.id.my_spiner)//默認(rèn)callback為ITEM_SELECTED void onItemSelected(int position) {Toast.makeText(this, "position: " + position, Toast.LENGTH_SHORT).show(); }@OnItemSelected(value = R.id.my_spiner, callback = OnItemSelected.Callback.NOTHING_SELECTED) void onNothingSelected() {Toast.makeText(this, "Nothing", Toast.LENGTH_SHORT).show(); }

    注意的是Spinner中只要有數(shù)據(jù),默認(rèn)都會(huì)選中第0個(gè)數(shù)據(jù),所以想進(jìn)入到onNothingSelected()方法,就需要把Adapter中的數(shù)據(jù)都清空

    ?

    4.6 使用findById

    Butter knife仍然包含了findById方法,用于仍需從一個(gè)view ,Activity,或者Dialog上 find view的時(shí)候。并且它可以自動(dòng)轉(zhuǎn)換類型。

    View view = LayoutInflater.from(context).inflate(R.layout.thing, null); TextView firstName = ButterKnife.findById(view, R.id.first_name); TextView lastName = ButterKnife.findById(view, R.id.last_name); ImageView photo = ButterKnife.findById(view, R.id.photo);

    4.7 代碼混淆(這個(gè)不用理解,知道有這個(gè)功能就行,因?yàn)槲乙矝]有明白)

    -keep class butterknife.** { *; } -dontwarn butterknife.internal.** -keep class **$$ViewBinder { *; }-keepclasseswithmembernames class * {@butterknife.* <fields>; }-keepclasseswithmembernames class * {@butterknife.* <methods>; }

    ?

    五、 原理

    利用了IOC的(Inverse of Controll)控制反轉(zhuǎn)結(jié)構(gòu),04年后改名為DI(dependency injection)依賴注入。目的是為了使類與類之間解耦合,提高系統(tǒng)的可擴(kuò)展性和可維護(hù)性。

    ?

    六、 和Dagger使用注意

    搭配Dagger使用的時(shí)候,ButterKnife可能會(huì)不起作用,沒效果,綁定控件為null。這時(shí)候把依賴包的annotationProcessor改為apt 就可以了:

    compile 'com.jakewharton:butterknife:8.5.1'//aptapt 'com.jakewharton:butterknife-compiler:8.5.1'

    ?

    好了,ButterKnife的基本使用就到這里的。如果只是想知道怎么使用,看到這里就可以了。下面會(huì)講講具體的原理代碼,對(duì)能力有一定的要求,大家自己決定看不看。

    ?

    ButterKnife 語(yǔ)法

    1. activity fragment 綁定與 fragment解綁

    想要使用ButterKnife,簡(jiǎn)單配置之后,我們還需要在Activity中onCreate()綁定,如下:

    @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 必須在setContentView()之后綁定ButterKnife.bind(this); }

    而如果使用fragment,官方給出的綁定以及解綁如下:

    public class FancyFragment extends Fragment {@BindView(R.id.button1) Button button1;@BindView(R.id.button2) Button button2;private Unbinder unbinder;@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fancy_fragment, container, false);// 綁定unbinder = ButterKnife.bind(this, view);// TODO Use fields...return view;}@Override public void onDestroyView() {super.onDestroyView();// 解綁unbinder.unbind();} }

    綁定之后,我們一起來看看,常用的幾種監(jiān)聽通過使用ButterKnife之后,我們又該如何編寫相關(guān)事件呢?別急,往下看~

    2.單擊事件

    首先我們先看看人家表層提供我們代碼中,我們可以得到哪兒些對(duì)我們有用的信息

    首先明確,targetType(目標(biāo)類型)為View,setter為setOnClickListener(單擊事件監(jiān)聽),type為ButterKnife封裝的單擊事件(butterknife.internal.DebouncingOnClickListener),而method中則是name為doClick以及parameters為View類型的倆個(gè)參數(shù);而下面的interface接口中需要我們傳遞一個(gè)id。

    簡(jiǎn)單了解后,我們衍生出三種寫法,如下:

    // 寫法1@OnClick(控件ID)void 方法名() {//業(yè)務(wù)邏輯操作}// 寫法2@OnClick(控件ID)void 方法名(控件類型) {//業(yè)務(wù)邏輯操作}// 寫法3@OnClick(控件ID)void 方法名(View view) {//業(yè)務(wù)邏輯操作}

    你可以按照上面指定一個(gè)個(gè)的寫,也可以綁定多個(gè),如官網(wǎng)提供下面寫法

    3.長(zhǎng)按事件

    同樣依舊看人家怎么寫的,看看我們能了解到什么

    和單擊事件對(duì)比,長(zhǎng)按時(shí)間則多出了一個(gè)returnType(返回值),且默認(rèn)為false。So,寫法如下~

    // 方法1@OnLongClick(控件ID)boolean 方法名(){// 業(yè)務(wù)邏輯操作return false;}// 方法2@OnLongClick(控件ID)boolean 方法名(控件類型){// 業(yè)務(wù)邏輯操作return false;}// 方法3@OnLongClick(控件ID)boolean 方法名(View view){// 業(yè)務(wù)邏輯操作return false;}

    4.Checked改變事件

    老規(guī)矩:

    改變,一般來說,會(huì)提供我們一個(gè)標(biāo)識(shí),去方便我們根據(jù)不同的狀態(tài)去處理不同的邏輯,so…

    // 寫法1@OnCheckedChanged(控件ID)void radioButtonCheckChange(boolean isl) {// 業(yè)務(wù)邏輯}// 寫法2@OnCheckedChanged(控件ID)void radioButtonCheckChange(控件類型,boolean isl) {// 業(yè)務(wù)邏輯}

    5.監(jiān)聽軟鍵盤右下角按鈕事件

    老規(guī)矩:

    so…經(jīng)過上面幾個(gè)大家可以知道,我們只需要對(duì)parameters以及是否是returnType重點(diǎn)關(guān)注即可。

    // 寫法1@OnEditorAction(控件ID)boolean 方法名() {// 業(yè)務(wù)邏輯操作return false;}// 寫法2// code:狀態(tài)碼@OnEditorAction(控件ID)boolean EditTextAction(int code) {// 業(yè)務(wù)邏輯操作return false;}// 寫法3// KeyEvent@OnEditorAction(控件ID)boolean EditTextAction(KeyEvent keyEvent) {// 業(yè)務(wù)邏輯操作return false;}// 寫法4@OnEditorAction(控件ID)boolean EditTextAction(int code, KeyEvent keyEvent) {// 業(yè)務(wù)邏輯操作return false;}// 寫法5@OnEditorAction(控件ID)boolean EditTextAction(TextView textView,int code, KeyEvent keyEvent) {// 業(yè)務(wù)邏輯操作return false;}

    6. EditText內(nèi)容改變監(jiān)聽事件

    由于源碼中內(nèi)容較長(zhǎng),不方便截圖,故截取部分代碼做解析,如下:

    @Target(METHOD) @Retention(CLASS) @ListenerClass(targetType = "android.widget.TextView",setter = "addTextChangedListener",remover = "removeTextChangedListener",type = "android.text.TextWatcher", ---> 這里同樣對(duì)之前的TextWatcher做了相關(guān)處理 gggcallbacks = OnTextChanged.Callback.class ---> 自定義枚舉,通過枚舉類型標(biāo)識(shí)當(dāng)前操作 666 ) public @interface OnTextChanged {/** View IDs to which the method will be bound. */@IdRes int[] value() default { View.NO_ID }; ---> 需要傳入ID/** Listener callback to which the method will be bound. */Callback callback() default Callback.TEXT_CHANGED; ---> 未改變狀態(tài)/** {@link TextWatcher} callback methods. */enum Callback { ---> 枚舉中分為三種類似 未改變 改變前 改變后/** {@link TextWatcher#onTextChanged(CharSequence, int, int, int)} */@ListenerMethod(name = "onTextChanged", ---> 當(dāng)前標(biāo)識(shí)為 未改變parameters = {"java.lang.CharSequence", ---> 用戶輸入字符"int", ---> 改變前個(gè)數(shù)"int", ---> 測(cè)試時(shí),返回0,沒整明白代表什么意思"int" ---> 根據(jù)打印結(jié)果,猜測(cè)這個(gè)應(yīng)該是每次增加內(nèi)容個(gè)數(shù)})TEXT_CHANGED,/** {@link TextWatcher#beforeTextChanged(CharSequence, int, int, int)} */@ListenerMethod(name = "beforeTextChanged", ---> 當(dāng)前標(biāo)識(shí)為 改變前parameters = {"java.lang.CharSequence", ---> 用戶輸入字符"int", ---> 改變前個(gè)數(shù)"int","int"})BEFORE_TEXT_CHANGED,/** {@link TextWatcher#afterTextChanged(android.text.Editable)} */@ListenerMethod(name = "afterTextChanged", ---> 當(dāng)前標(biāo)識(shí)為 改變后parameters = "android.text.Editable" ---> 用戶輸入字符)AFTER_TEXT_CHANGED, ---> 我們關(guān)注的重點(diǎn)在此,每次只需要監(jiān)聽這個(gè),去做相關(guān)處理即可}

    從上得知,關(guān)于EditText內(nèi)容改變事件,我們關(guān)注點(diǎn)只在乎改變后的內(nèi)容格式(個(gè)數(shù))是否符合項(xiàng)目需求,而其他可以暫時(shí)忽略,從而衍生下面寫法:

    // 內(nèi)容改變后監(jiān)聽// Editable editable:用戶輸入字符@OnTextChanged(value = 控件ID, callback = 監(jiān)聽類型,改變后取值為:OnTextChanged.Callback.AFTER_TEXT_CHANGED)void editTextChangeAfter(Editable editable) {// 業(yè)務(wù)邏輯}// 內(nèi)容改變前監(jiān)聽@OnTextChanged(value = 控件ID, callback = 監(jiān)聽類型,改變前取值為:OnTextChanged.Callback.BEFORE_TEXT_CHANGED)void editTextChangeBefore(CharSequence s, int start) {// 業(yè)務(wù)邏輯}// 內(nèi)容未發(fā)生改變監(jiān)聽@OnTextChanged(value = 控件ID, callback = 監(jiān)聽類型,取值為:OnTextChanged.Callback.TEXT_CHANGED)void editTextChange(CharSequence s, int start) {// 業(yè)務(wù)邏輯}

    7. 焦點(diǎn)監(jiān)聽事件

    老規(guī)矩:

    由此可見,如下:

    @OnFocusChange(控件ID)void editTextFocus(boolean isl){// 業(yè)務(wù)邏輯}

    8. 觸摸監(jiān)聽事件

    老規(guī)矩:

    寫法如下:

    @OnTouch(控件ID)boolean imageView(MotionEvent event){// 業(yè)務(wù)邏輯return false;}

    ?

    9. item項(xiàng)單擊監(jiān)聽事件

    老規(guī)矩:

    so…

    @OnItemClick(控件ID)void listItemClick(int position){// 業(yè)務(wù)邏輯}

    10. item項(xiàng)長(zhǎng)按監(jiān)聽事件

    老規(guī)矩:

    so…

    @OnItemLongClick(R.id.listView)boolean listItemLongClick(int position) {Toast.makeText(this, "OnItemLongClick---點(diǎn)擊了第" + position + "個(gè)", Toast.LENGTH_SHORT).show();return true;}

    ?

    簡(jiǎn)單總結(jié)一下,ButterKnife就是一個(gè)框架,用注解來取代了findviewbyid的功能,而且它是編譯器完成的,對(duì)于運(yùn)行沒有任何的效率的影響。使用ButterKnife最好是下載對(duì)應(yīng)的插件Android ButterKnife Zelezny,具體怎么下載,我下一步博客再講。

    ?

    android ButterKnife的簡(jiǎn)單使用就講完了。

    ?

    就這么簡(jiǎn)單。

    總結(jié)

    以上是生活随笔為你收集整理的android ButterKnife的简单使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。