ButterKnife的原理及如何使用(butterknife,移动开发)

时间:2024-05-06 10:32:39 作者 : 石家庄SEO 分类 : 移动开发
  • TAG :

前言

话说,Android开发的兄弟们都知道,每次初始化控件,设置相应的事件,写的那点过程多而且恶心。我们先一块回顾下不堪的曾经~那些年,我们是这样初始化控件:

//每次的习惯上来写一个initView()方法tvContent=(TextView)findViewById(R.id.btn_content);//遇到项目大的时候,这里面的东西,也曾占据半壁江山。。。苦不堪言//当然也曾封装过方法,避免各种findViewById,但是依旧如此。。。

那些年,我们是这样设置事件:

tvContent.setOnClickListener(this);//当然,LZ的习惯依旧扔到initView中,让他们尽情的浪荡,放纵~

But,骚年,身为一个Android开发,你还能继续忍受这种不堪的摧残么?答案当然不能!

那么,接下来为大家带来一个神器,助我们开发高效,快捷~

ButterKnife 初识

ButterKnife,又被戏称为黄油刀,至于为什么被戏称为这个,大家可以看下面附上的从官方截取的icon~

ButterKnife的原理及如何使用

一块桌布,一个盘子,一个Android小机器人形状的黄油,一把刀。这些合起来被大家戏称为黄油刀。(我说呢,纠结我半天,都搞不懂黄油刀是个什么鬼,这次晓得了)icon下面简单解释就是为Android 视图(View)提供绑定字段和方法。 也就是说,我们今后可以通过这把刀去替换之前琐碎的初始化~

大家有兴趣的也可以去官网上看看,下面为大家附上官网地址以及GitHub地址捎带的附带个api地址。

官方地址:http://jakewharton.github.io/butterknife/

GitHub地址:https://github.com/JakeWharton/butterknife

API访问地址:http://jakewharton.github.io/butterknife/javadoc/

话说,简单了解之后,还是来点干货吧~不然说不过去哈

首先我们要明白,ButterKnife 是出自Android大神JakeWharton之手的一个开源库,它的作用就是通过注解绑定视图的方法,从而简化代码量(减少我们当年findViewById以及设置事件时编写的大量代码)。

而我们使用一个东西,必须要知道他的优势在哪儿?我用它能给我带来什么方便之处?那么接下来,我们看看这把“黄油刀”有着什么样的优势,从而能简化我们一些代码?

ButterKnife 优势

1. 强大的View绑定,Click事件处理功能以及资源内容,简化代码,提升开发效率;

2. 方便的处理Adapter里的ViewHolder绑定问题;

3. 运行时不会影响APP效率,使用配置方便;

4. 代码清晰,可读性强。

了解完ButterKnife优势后,怀着好奇心,我们看看他都支持哪儿些方面,换句话说就是,我们开发过程中,在什么情况下可以通过使用ButterKnife去减少我们曾经的代码量?

ButterKnife 使用场景

  • View(视图)绑定:例如初始化控件;

  • 资源绑定:例如color,string等;

  • 非Activity绑定:这里值得是当时用 fragment 的时候;

  • View List 绑定: Adapter 中 ViewHolder,具体使用会在下方讲解;

  • Listener 绑定:这个就好理解了,也就是平时控件所需监听事件。

ButterKnife 语法

1. activity fragment 绑定与 fragment解绑

想要使用ButterKnife,简单配置之后,我们还需要在Activity中onCreate()绑定,如下:

@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//必须在setContentView()之后绑定ButterKnife.bind(this);}

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

publicclassFancyFragmentextendsFragment{@BindView(R.id.button1)Buttonbutton1;@BindView(R.id.button2)Buttonbutton2;privateUnbinderunbinder;@OverridepublicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){Viewview=inflater.inflate(R.layout.fancy_fragment,container,false);//绑定unbinder=ButterKnife.bind(this,view);//TODOUsefields...returnview;}@OverridepublicvoidonDestroyView(){super.onDestroyView();//解绑unbinder.unbind();}}

绑定之后,我们一起来看看,常用的几种监听通过使用ButterKnife之后,我们又该如何编写相关事件呢?别急,往下看~

2.单击事件

首先我们先看看人家表层提供我们代码中,我们可以得到哪儿些对我们有用的信息

ButterKnife的原理及如何使用

首先明确,targetType(目标类型)为View,setter为setOnClickListener(单击事件监听),type为ButterKnife封装的单击事件(butterknife.internal.DebouncingOnClickListener),而method中则是name为doClick以及parameters为View类型的俩个参数;而下面的interface接口中需要我们传递一个id。

简单了解后,我们衍生出三种写法,如下:

//写法1@OnClick(控件ID)void方法名(){//业务逻辑操作}//写法2@OnClick(控件ID)void方法名(控件类型){//业务逻辑操作}//写法3@OnClick(控件ID)void方法名(Viewview){//业务逻辑操作}

你可以按照上面指定一个个的写,也可以绑定多个,如官网提供下面写法:

ButterKnife的原理及如何使用

3.长按事件

同样依旧看人家怎么写的,看看我们能了解到什么

ButterKnife的原理及如何使用

和单击事件对比,长按时间则多出了一个returnType(返回值),且默认为false。So,写法如下~

//方法1boolean方法名(){//业务逻辑操作returnfalse;}//方法2boolean方法名(控件类型){//业务逻辑操作returnfalse;}//方法3boolean方法名(Viewview){//业务逻辑操作returnfalse;}

4.Checked改变事件

老规矩:

ButterKnife的原理及如何使用

改变,一般来说,会提供我们一个标识,去方便我们根据不同的状态去处理不同的逻辑,so...

//写法1@OnCheckedChanged(控件ID)voidradioButtonCheckChange(booleanisl){//业务逻辑}//写法2@OnCheckedChanged(控件ID)voidradioButtonCheckChange(控件类型,booleanisl){//业务逻辑}

5.监听软键盘右下角按钮事件

老规矩:

ButterKnife的原理及如何使用

so...经过上面几个大家可以知道,我们只需要对parameters以及是否是returnType重点关注即可。

//写法1@OnEditorAction(控件ID)boolean方法名(){//业务逻辑操作returnfalse;}//写法2//code:状态码@OnEditorAction(控件ID)booleanEditTextAction(intcode){//业务逻辑操作returnfalse;}//写法3//KeyEvent@OnEditorAction(控件ID)booleanEditTextAction(KeyEventkeyEvent){//业务逻辑操作returnfalse;}//写法4@OnEditorAction(控件ID)booleanEditTextAction(intcode,KeyEventkeyEvent){//业务逻辑操作returnfalse;}//写法5@OnEditorAction(控件ID)booleanEditTextAction(TextViewtextView,intcode,KeyEventkeyEvent){//业务逻辑操作returnfalse;}

6. EditText内容改变监听事件

由于源码中内容较长,不方便截图,故截取部分代码做解析,如下:

@Target(METHOD)@Retention(CLASS)@ListenerClass(targetType="android.widget.TextView",setter="addTextChangedListener",remover="removeTextChangedListener",type="android.text.TextWatcher",--->这里同样对之前的TextWatcher做了相关处理gggcallbacks=OnTextChanged.Callback.class--->自定义枚举,通过枚举类型标识当前操作666)public@interfaceOnTextChanged{/**ViewIDstowhichthemethodwillbebound.*/@IdResint[]value()default{View.NO_ID};--->需要传入ID/**Listenercallbacktowhichthemethodwillbebound.*/Callbackcallback()defaultCallback.TEXT_CHANGED;--->未改变状态/**{@linkTextWatcher}callbackmethods.*/enumCallback{--->枚举中分为三种类似未改变改变前改变后/**{@linkTextWatcher#onTextChanged(CharSequence,int,int,int)}*/@ListenerMethod(name="onTextChanged",--->当前标识为未改变parameters={"java.lang.CharSequence",--->用户输入字符"int",--->改变前个数"int",--->测试时,返回0,没整明白代表什么意思"int"--->根据打印结果,猜测这个应该是每次增加内容个数})TEXT_CHANGED,/**{@linkTextWatcher#beforeTextChanged(CharSequence,int,int,int)}*/@ListenerMethod(name="beforeTextChanged",--->当前标识为改变前parameters={"java.lang.CharSequence",--->用户输入字符"int",--->改变前个数"int","int"})BEFORE_TEXT_CHANGED,/**{@linkTextWatcher#afterTextChanged(android.text.Editable)}*/@ListenerMethod(name="afterTextChanged",--->当前标识为改变后parameters="android.text.Editable"--->用户输入字符)AFTER_TEXT_CHANGED,--->我们关注的重点在此,每次只需要监听这个,去做相关处理即可}

从上得知,关于EditText内容改变事件,我们关注点只在乎改变后的内容格式(个数)是否符合项目需求,而其他可以暂时忽略,从而衍生下面写法:

//内容改变后监听//Editableeditable:用户输入字符@OnTextChanged(value=控件ID,callback=监听类型,改变后取值为:OnTextChanged.Callback.AFTER_TEXT_CHANGED)voideditTextChangeAfter(Editableeditable){//业务逻辑}//内容改变前监听@OnTextChanged(value=控件ID,callback=监听类型,改变前取值为:OnTextChanged.Callback.BEFORE_TEXT_CHANGED)voideditTextChangeBefore(CharSequences,intstart){//业务逻辑}//内容未发生改变监听@OnTextChanged(value=控件ID,callback=监听类型,取值为:OnTextChanged.Callback.TEXT_CHANGED)voideditTextChange(CharSequences,intstart){//业务逻辑}

7. 焦点监听事件

老规矩:

ButterKnife的原理及如何使用

由此可见,如下:

@OnFocusChange(控件ID)voideditTextFocus(booleanisl){//业务逻辑}

8. 触摸监听事件

老规矩:

ButterKnife的原理及如何使用

写法如下:

@OnTouch(控件ID)booleanimageView(MotionEventevent){//业务逻辑returnfalse;}

9. item项单击监听事件

老规矩:

ButterKnife的原理及如何使用

so...

@OnItemClick(控件ID)voidlistItemClick(intposition){//业务逻辑}

10. item项长按监听事件

老规矩:

ButterKnife的原理及如何使用

so...

@OnItemLongClick(R.id.listView)booleanlistItemLongClick(intposition){Toast.makeText(this,"OnItemLongClick---点击了第"+position+"个",Toast.LENGTH_SHORT).show();returntrue;}

ButterKnife 使用注意

1.Activity ButterKnife.bind(this) 必须在 setContentView() 之后,且父类 bind 绑定后,子类不需要再 bind;

2.Fragment 中使用需要传入view:Fragment ButterKnife.bind(this, mRootView);

3.属性布局不能用private or static 修饰,否则会报错;

4.setContentView()不能通过注解实现。(其他的有些注解框架可以)

通过上面简单介绍,相信大家对这把刀已经有了一个初步的理解,那么如何在Android Studio中通过使用这把刀从而改善我们的代码呢?我们接着往下瞧。

Android Studio使用ButterKnife前期准备操作

想要在Android Studio中使用ButterKnife,首先需要下载安装ButterKnife插件,之后经过简单配置之后方可使用~

第一步:Android Studio集成ButterKnife插件

1.点击 File ---> Settings... ---> 选择 Plugins(也可以使用<font color=#FF0000>快捷键 Ctrl+Alt+S)

ButterKnife的原理及如何使用

2.输入ButterKnife,选择“Android ButterKnife Zelezny”,点击安装(LZ这里已经安装好了),稍后Android Studio会提示重启AS,确认即可。

ButterKnife的原理及如何使用

3.经过以上简单俩步,我们的Android Studio又get了新技能,那就是:支持ButterKnife插件!

第二步:配置ButterKnife

1.使用前,我们需要对ButterKnife进行简单配置( 为我们的项目引入'com.jakewharton:butterknifecompiler:8.5.1','com.jakewharton:butterknife:8.5.1' ),引入过程如下所示:

ButterKnife的原理及如何使用

ButterKnife的原理及如何使用

2.引入完成之后,我们先来小试牛刀~得瑟得瑟

在MainActivity中的onCreate 右键layout,选择Generate... ,Generate ButterKnife Injections,选择要使用注解的控件,点击Confirm

ButterKnife的原理及如何使用

一键可视化操作,方便快捷~进过上面的配置后,我们可以在项目中尽情的使用ButterKnife各种秀了~

刀法一部曲,玩转常用事件监听

1.在MainActivity布局中新增几个常用控件,通过右键layout,选择Generate... ,Generate ButterKnife Injections,选择要使用注解的控件,点击Confirm ,从而生成我们接下来演示根本(后面会有所更改),如下图所示~

ButterKnife的原理及如何使用

接下来为大家演示相关事件使用,一点点玩转黄油刀

1. 单击事件(以TextView为例)

代码如下:

@OnClick(R.id.text)voidtextClick(){Toast.makeText(MainActivity.this,"TextView的单击事件触发。。。(无参-默认)",Toast.LENGTH_SHORT).show();}@OnClick(R.id.text)voidtextClick(TextViewtextView){Toast.makeText(MainActivity.this,"TextView的单击事件触发。。。(TextView)",Toast.LENGTH_SHORT).show();}@OnClick(R.id.text)voidtextClick(Viewview){Toast.makeText(MainActivity.this,"TextView的单击事件触发。。。(View)",Toast.LENGTH_SHORT).show();}

运行结果展示:

ButterKnife的原理及如何使用

2. 长按事件(以Button为例)

代码如下:

@OnLongClick(R.id.button)booleanbuttonLongClick(){Toast.makeText(MainActivity.this,"Button的长按事件触发。。。(无参-默认)",Toast.LENGTH_SHORT).show();returnfalse;}//@OnLongClick(R.id.button)//booleanbuttonLongClick(Buttonbutton){//Toast.makeText(MainActivity.this,"Button的长按事件触发。。。(TextView)",Toast.LENGTH_SHORT).show();//returnfalse;//}//@OnLongClick(R.id.button)//booleanbuttonLongClick(Viewview){//Toast.makeText(MainActivity.this,"Button的长按事件触发。。。(View)",Toast.LENGTH_SHORT).show();//returnfalse;//}

运行结果如下:

ButterKnife的原理及如何使用

这里大家可能会问了,LZ你干嘛要把下面的注释掉了呢,是不是不能用呢?确实,一开始没有注释,运行时候出现异常,提示如下:

MultiplelistenermethodswithreturnvaluespecifiedforID:2131165193

LZ理解为,这个监听只会为ID(2131165193)返回相应监听,也就是一一对应!so... 一山不容二虎,除非一公一母啊~

3. Checked改变事件(以CheckBox为例)

代码如下:

@OnCheckedChanged(R.id.checkBox)voidradioButtonCheckChange(booleanisl){Toast.makeText(MainActivity.this,"CheckBox。。。(无参)"+isl,Toast.LENGTH_SHORT).show();}@OnCheckedChanged(R.id.checkBox)voidradioButtonCheckChange(CheckBoxcheckBox,booleanisl){Toast.makeText(MainActivity.this,"CheckBox。。。(CheckBox)"+isl,Toast.LENGTH_SHORT).show();}

运行结果如下:

ButterKnife的原理及如何使用

4. 监听软键盘右下角按钮事件

代码如下:

//@OnEditorAction(R.id.tv_editor_action)//booleanEditTextAction(){//Toast.makeText(MainActivity.this,"点击---通往天堂无参",Toast.LENGTH_SHORT).show();//returnfalse;//}//@OnEditorAction(R.id.tv_editor_action)//booleanEditTextAction(intcode){//Toast.makeText(MainActivity.this,"点击---通往天堂code:"+code,Toast.LENGTH_SHORT).show();//returnfalse;//}//@OnEditorAction(R.id.tv_editor_action)//booleanEditTextAction(KeyEventkeyEvent){//Toast.makeText(MainActivity.this,"点击---通往天堂KeyEvent:"+keyEvent,Toast.LENGTH_SHORT).show();//returnfalse;//}//@OnEditorAction(R.id.tv_editor_action)//booleanEditTextAction(intcode,KeyEventkeyEvent){//Toast.makeText(MainActivity.this,"点击---通往天堂code:"+code+"KeyEvent:"+keyEvent,Toast.LENGTH_SHORT).show();//returnfalse;//}@OnEditorAction(R.id.tv_editor_action)booleanEditTextAction(TextViewtextView,intcode,KeyEventkeyEvent){Toast.makeText(MainActivity.this,textView.getText().toString()+"点击---通往天堂code:"+code+"KeyEvent:"+keyEvent,Toast.LENGTH_SHORT).show();returnfalse;}

运行效果下:

ButterKnife的原理及如何使用

5. EditText内容改变监听事件

代码如下:

@OnTextChanged(value=R.id.editText,callback=OnTextChanged.Callback.AFTER_TEXT_CHANGED)voideditTextChangeAfter(Editableeditable){Toast.makeText(MainActivity.this,"改变后内容为:"+editable.toString(),Toast.LENGTH_SHORT).show();System.out.println("改变后---内容为:"+editable.toString());}@OnTextChanged(value=R.id.editText,callback=OnTextChanged.Callback.BEFORE_TEXT_CHANGED)voideditTextChangeBefore(CharSequences,intstart,intbefore,intcount){Toast.makeText(MainActivity.this,"编辑内容为:"+s+",开始前个数:"+start,Toast.LENGTH_SHORT).show();System.out.println("改变前---内容为:"+s+",开始前个数:"+start+",:"+before+","+count);}@OnTextChanged(value=R.id.editText,callback=OnTextChanged.Callback.TEXT_CHANGED)voideditTextChange(CharSequences,intstart,intbefore,intcount){Toast.makeText(MainActivity.this,"编辑内容为:"+s+",开始前个数:"+start,Toast.LENGTH_SHORT).show();System.out.println("未编辑---内容为:"+s+",开始前个数:"+start+","+before+","+count);}

运行结果如下:

ButterKnife的原理及如何使用

6.焦点监听事件

代码如下:

@OnFocusChange(R.id.editTextFocus)voideditTextFocus(booleanisl){if(isl){Toast.makeText(MainActivity.this,"获取焦点"+isl,Toast.LENGTH_SHORT).show();}else{Toast.makeText(MainActivity.this,"失去焦点"+isl,Toast.LENGTH_SHORT).show();}}

运行结果如下:

ButterKnife的原理及如何使用

7. 触摸监听事件

代码如下:

@OnTouch(R.id.imageView)booleanimageView(MotionEventevent){System.out.println(event);returnfalse;}

运行结果如下:

04-1011:47:04.50432627-32627/cn.hlq.butterknifestudyI/System.out:MotionEvent{action=ACTION_DOWN,actionButton=0,id[0]=0,x[0]=189.8265,y[0]=148.42676,toolType[0]=TOOL_TYPE_FINGER,buttonState=0,metaState=0,flags=0x0,edgeFlags=0x0,pointerCount=1,historySize=0,eventTime=6743683,downTime=6743683,deviceId=1,source=0x1002}

8. item单击以及长按监听事件

代码如下:

@OnItemClick(R.id.listView)voidlistItemClick(intposition){Toast.makeText(this,"OnItemClick---点击了第"+position+"个",Toast.LENGTH_SHORT).show();}@OnItemLongClick(R.id.listView)booleanlistItemLongClick(intposition){Toast.makeText(this,"OnItemLongClick---点击了第"+position+"个",Toast.LENGTH_SHORT).show();returntrue;}

运行结果如下:

ButterKnife的原理及如何使用

想必大家通过以上已经掌握这套刀法基本使用了,那么上面曾说过,还可以对Adapter进行改造,从而节省开发过程中一些编码,那就一块瞅瞅呗~

刀法二部曲,巧用Adapter

创建一个item_layout作为接下来演示用~

<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:id="@+id/item_username"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:layout_weight="1"/><TextViewandroid:id="@+id/item_userPwd"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:layout_weight="1"/></LinearLayout>

很简单,没什么东西,接下来看adapter~

packagecn.hlq.butterknifestudy.adapter;importandroid.content.Context;importandroid.view.LayoutInflater;importandroid.view.View;importandroid.view.ViewGroup;importandroid.widget.BaseAdapter;importandroid.widget.TextView;importjava.util.ArrayList;importjava.util.List;importbutterknife.BindView;importbutterknife.ButterKnife;importcn.hlq.butterknifestudy.R;importcn.hlq.butterknifestudy.model.Student;/***CreatedbyHLQon2017/4/110011.*/publicclassListViewAdapterextendsBaseAdapter{privateContextcontext;privateList<Student>stuList=newArrayList<Student>();publicListViewAdapter(Contextcontext,List<Student>stuList){this.context=context;this.stuList=stuList;}@OverridepublicintgetCount(){returnstuList!=null?stuList.size():0;}@OverridepublicObjectgetItem(intposition){returnstuList!=null?stuList.get(position):null;}@OverridepubliclonggetItemId(intposition){returnposition;}@OverridepublicViewgetView(intposition,ViewconvertView,ViewGroupparent){ViewHolderviewHolder=null;if(viewHolder==null){convertView=LayoutInflater.from(context).inflate(R.layout.item_listview_show,null);viewHolder=newViewHolder(convertView);convertView.setTag(viewHolder);}else{viewHolder=(ViewHolder)convertView.getTag();}Studentstu=stuList.get(position);viewHolder.itemUsername.setText(stu.getUserName());viewHolder.itemUserPwd.setText(stu.getUserPwd());returnconvertView;}staticclassViewHolder{@BindView(R.id.item_username)TextViewitemUsername;@BindView(R.id.item_userPwd)TextViewitemUserPwd;ViewHolder(Viewview){ButterKnife.bind(this,view);}}}

运行结果为:

ButterKnife的原理及如何使用

在此告诉大家一个小秘密,你可以直接右键layout,在生成注解时,选择自动创建ViewHolder,如下图:

ButterKnife的原理及如何使用

是不是相当方便?在此,顺便捎带脚的介绍下,如何使用这把刀玩玩资源内容呢?

//初始化指定默认值@BindString(R.string.app_test)StringtitleContent;lvTitle.setText(titleContent);

运行结果如下:

ButterKnife的原理及如何使用

除以上,刀法中还包含对以下支持,大家有兴趣自己了解即可,没什么难度了

ButterKnife的原理及如何使用

而且官方上也提供了一些基本的使用,如下:

ButterKnife的原理及如何使用

刀法三部曲BaseActivity封装,进一步简化代码

通常我们会封装一个BaseActivity,里面写好常用内容,之后activity继承此BaseActivity。同样我们也可以在此进行初始化,避免我们多次初始化,看下面一波代码~

packagecom.heliquan.butterknife.base;importandroid.app.Activity;importandroid.content.Context;importandroid.os.Bundle;importandroid.support.annotation.LayoutRes;importandroid.view.KeyEvent;importandroid.view.View;importandroid.view.ViewGroup;importbutterknife.ButterKnife;importbutterknife.Unbinder;/***createdbyheliquanat2023年4月14日*/publicabstractclassBaseActivityextendsActivity{privateUnbinderunbinder;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);//必须重写setContentView()的三个方法,不然会出现子类继承无效,具体原因没有深入了解setContentView(getContentViewId());unbinder=ButterKnife.bind(this);}@OverridepublicvoidsetContentView(@LayoutResintlayoutResID){super.setContentView(layoutResID);unbinder=ButterKnife.bind(this);}@OverridepublicvoidsetContentView(Viewview){super.setContentView(view);unbinder=ButterKnife.bind(this);}@OverridepublicvoidsetContentView(Viewview,ViewGroup.LayoutParamsparams){super.setContentView(view,params);unbinder=ButterKnife.bind(this);}/***获取内容id*/protectedabstractintgetContentViewId();/***初始化View*/protectedabstractvoidinitView();@OverrideprotectedvoidonDestroy(){super.onDestroy();unbinder.unbind();}/***根据id返回资源内容**@paramcontext*@paramstrId*@return*/protectedStringgetStrResource(Activityactivity,intstrId){returnactivity.getResources().getString(strId);}/***监听返回按钮,点击返回finish当前页面**@paramkeyCode*@paramevent*@return*/@OverridepublicbooleanonKeyDown(intkeyCode,KeyEventevent){if(keyCode==KeyEvent.KEYCODE_BACK&&event.getRepeatCount()==0){finish();returntrue;}returnsuper.onKeyDown(keyCode,event);}}
 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:ButterKnife的原理及如何使用的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:在UI主线程中的耗时操作有什么下一篇:

11 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18