java黄油刀_一篇文章玩转ButterKnife,让代码更简洁

前言

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

// 每次的习惯上来写一个initView()方法

tvContent = (TextView) findViewById(R.id.btn_content);

// 遇到项目大的时候,这里面的东西,也曾占据半壁江山。。。苦不堪言

// 当然也曾封装过方法,避免各种findViewById,但是依旧如此。。。

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

tvContent.setOnClickListener(this);

// 当然,LZ的习惯依旧扔到initView中,让他们尽情的浪荡,放纵~

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

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

ButterKnife 初识

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

d286465cab6c849f3defe8eb60c3f9b5.png

一块桌布,一个盘子,一个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()绑定,如下:

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

// 必须在setContentView()之后绑定

ButterKnife.bind(this);

}

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

publicclass FancyFragment extends Fragment {

@BindView(R.id.button1) Button button1;

@BindView(R.id.button2) Button button2;

private Unbinder unbinder;

@Override publicViewonCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

Viewview= inflater.inflate(R.layout.fancy_fragment, container,false);

// 绑定

unbinder = ButterKnife.bind(this, view);

// TODO Use fields...

returnview;

}

@Override publicvoid onDestroyView() {

super.onDestroyView();

// 解绑

unbinder.unbind();

}

}

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

2.单击事件

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

514b439a0252d8a36f30fce3fa802e70.png

首先明确,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) {

//业务逻辑操作

}

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

f39920b056825a32b9182897749e216a.png

3.长按事件

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

f67a274aa54a284d794487f8f6ff5f42.png

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

// 方法1

boolean 方法名(){

// 业务逻辑操作

returnfalse;

}

// 方法2

boolean 方法名(控件类型){

// 业务逻辑操作

returnfalse;

}

// 方法3

boolean 方法名(Viewview){

// 业务逻辑操作

returnfalse;

}

4.Checked改变事件

老规矩:

9d1eb720621742ccd17cfa1900488be0.png

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

// 写法1

@OnCheckedChanged(控件ID)

void radioButtonCheckChange(boolean isl) {

// 业务逻辑

}

// 写法2

@OnCheckedChanged(控件ID)

void radioButtonCheckChange(控件类型,boolean isl) {

// 业务逻辑

}

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

老规矩:

2a6416554ea7d8d90f5c0f227285d95c.png

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

// 写法1

@OnEditorAction(控件ID)

boolean 方法名() {

// 业务逻辑操作

returnfalse;

}

// 写法2

// code:状态码

@OnEditorAction(控件ID)

boolean EditTextAction(intcode) {

// 业务逻辑操作

returnfalse;

}

// 写法3

// KeyEvent

@OnEditorAction(控件ID)

boolean EditTextAction(KeyEvent keyEvent) {

// 业务逻辑操作

returnfalse;

}

// 写法4

@OnEditorAction(控件ID)

boolean EditTextAction(intcode, KeyEvent keyEvent) {

// 业务逻辑操作

returnfalse;

}

// 写法5

@OnEditorAction(控件ID)

boolean EditTextAction(TextView textView,intcode, KeyEvent keyEvent) {

// 业务逻辑操作

returnfalse;

}

6. EditText内容改变监听事件

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

@Target(METHOD)

@Retention(CLASS)

@ListenerClass(

targetType = "android.widget.TextView",

setter = "addTextChangedListener",

remover = "removeTextChangedListener",

type = "android.text.TextWatcher",--->   这里同样对之前的TextWatcher做了相关处理 ggg

callbacks = OnTextChanged.Callback.class   --->   自定义枚举,通过枚举类型标识当前操作 666

)

public@interface OnTextChanged {

/** ViewIDstowhich the method will be bound. */

@IdRes int[] value()default{View.NO_ID };--->   需要传入ID

/** Listener callback towhich the method will be bound. */

Callback callback() defaultCallback.TEXT_CHANGED;--->  未改变状态

/** {@link TextWatcher} callback methods. */

enum Callback {  --->  枚举中分为三种类似 未改变 改变前 改变后

/** {@link TextWatcher#onTextChanged(CharSequence, int,int,int)} */

@ListenerMethod(

name="onTextChanged",--->  当前标识为 未改变

parameters = {

"java.lang.CharSequence",--->  用户输入字符

"int",--->  改变前个数

"int",--->  测试时,返回0,没整明白代表什么意思

"int"--->  根据打印结果,猜测这个应该是每次增加内容个数

}

)

TEXT_CHANGED,

/** {@link TextWatcher#beforeTextChanged(CharSequence, int,int,int)} */

@ListenerMethod(

name="beforeTextChanged",--->  当前标识为 改变前

parameters = {

"java.lang.CharSequence",--->  用户输入字符

"int",--->  改变前个数

"int",

"int"

}

)

BEFORE_TEXT_CHANGED,

/** {@link TextWatcher#afterTextChanged(android.text.Editable)} */

@ListenerMethod(

name="afterTextChanged",--->  当前标识为 改变后

parameters = "android.text.Editable"--->  用户输入字符

)

AFTER_TEXT_CHANGED, --->  我们关注的重点在此,每次只需要监听这个,去做相关处理即可

}

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

// 内容改变后监听

// Editable editable:用户输入字符

@OnTextChanged(value = 控件ID, callback = 监听类型,改变后取值为:OnTextChanged.Callback.AFTER_TEXT_CHANGED)

void editTextChangeAfter(Editable editable) {

// 业务逻辑

}

// 内容改变前监听

@OnTextChanged(value = 控件ID, callback = 监听类型,改变前取值为:OnTextChanged.Callback.BEFORE_TEXT_CHANGED)

void editTextChangeBefore(CharSequence s, intstart) {

// 业务逻辑

}

// 内容未发生改变监听

@OnTextChanged(value = 控件ID, callback = 监听类型,取值为:OnTextChanged.Callback.TEXT_CHANGED)

void editTextChange(CharSequence s, intstart) {

// 业务逻辑

}

7. 焦点监听事件

老规矩:

5d66910b3a03adee69f17875da98a871.png

由此可见,如下:

@OnFocusChange(控件ID)

void editTextFocus(boolean isl){

// 业务逻辑

}

8. 触摸监听事件

老规矩:

74d9ef55a4cd25bc3a3a30ee54e378da.png

写法如下:

@OnTouch(控件ID)

boolean imageView(MotionEvent event){

// 业务逻辑

returnfalse;

}

9. item项单击监听事件

老规矩:

2e57a692edde34aafe840b8430c373ac.png

so...

@OnItemClick(控件ID)

void listItemClick(intposition){

// 业务逻辑

}

10. item项长按监听事件

老规矩:

d51b7be29f5fa111fe26864c6e26511d.png

so...

@OnItemLongClick(R.id.listView)

boolean listItemLongClick(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(也可以使用快捷键 Ctrl+Alt+S)

1ca638f0c3a995d7da897d97b4120685.png

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

21b1dc639a0890ba93f4694092f5e521.png

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

第二步:配置ButterKnife

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

819ccf9641847e37c4d2d47a8a48f555.png

136f0e39aa2170cb7efde7fb097db289.png

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

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

723b8c7bce93ca76aa05a7dd49bfdb40.gif

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

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

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

062fab49b2e168ed0fff201234fb12f0.png

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

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

代码如下:

@OnClick(R.id.text)

void textClick() {

Toast.makeText(MainActivity.this, "TextView的单击事件触发。。。(无参-默认)", Toast.LENGTH_SHORT).show();

}

@OnClick(R.id.text)

void textClick(TextView textView){

Toast.makeText(MainActivity.this, "TextView的单击事件触发。。。(TextView)", Toast.LENGTH_SHORT).show();

}

@OnClick(R.id.text)

void textClick(Viewview){

Toast.makeText(MainActivity.this, "TextView的单击事件触发。。。(View)", Toast.LENGTH_SHORT).show();

}

运行结果展示:

e4cce848e8ed3d787ef6dc4bcc2a379a.gif

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

代码如下:

@OnLongClick(R.id.button)

boolean buttonLongClick(){

Toast.makeText(MainActivity.this, "Button的长按事件触发。。。(无参-默认)", Toast.LENGTH_SHORT).show();

returnfalse;

}

//    @OnLongClick(R.id.button)

//    boolean buttonLongClick(Button button){

//        Toast.makeText(MainActivity.this, "Button的长按事件触发。。。(TextView)", Toast.LENGTH_SHORT).show();

//        returnfalse;

//    }

//    @OnLongClick(R.id.button)

//    boolean buttonLongClick(Viewview){

//        Toast.makeText(MainActivity.this, "Button的长按事件触发。。。(View)", Toast.LENGTH_SHORT).show();

//        returnfalse;

//    }

运行结果如下:

c1d8fb73622d1f8443a50d6a224ae54f.gif

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

Multiple listener methodswithreturnvalue specifiedforID:2131165193

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

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

代码如下:

@OnCheckedChanged(R.id.checkBox)

void radioButtonCheckChange(boolean isl) {

Toast.makeText(MainActivity.this, "CheckBox。。。(无参)"+ isl, Toast.LENGTH_SHORT).show();

}

@OnCheckedChanged(R.id.checkBox)

void radioButtonCheckChange(CheckBox checkBox,boolean isl) {

Toast.makeText(MainActivity.this, "CheckBox。。。(CheckBox)"+ isl, Toast.LENGTH_SHORT).show();

}

运行结果如下:

ecc35c9957a89b88afba770b2f379971.gif

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

代码如下:

//    @OnEditorAction(R.id.tv_editor_action)

//    boolean EditTextAction() {

//        Toast.makeText(MainActivity.this, " 点击---通往天堂 无参", Toast.LENGTH_SHORT).show();

//        returnfalse;

//    }

//    @OnEditorAction(R.id.tv_editor_action)

//    boolean EditTextAction(intcode) {

//        Toast.makeText(MainActivity.this, " 点击---通往天堂 code:"+code, Toast.LENGTH_SHORT).show();

//        returnfalse;

//    }

//    @OnEditorAction(R.id.tv_editor_action)

//    boolean EditTextAction(KeyEvent keyEvent) {

//        Toast.makeText(MainActivity.this, "点击---通往天堂 KeyEvent:"+keyEvent, Toast.LENGTH_SHORT).show();

//        returnfalse;

//    }

//    @OnEditorAction(R.id.tv_editor_action)

//    boolean EditTextAction(intcode, KeyEvent keyEvent) {

//        Toast.makeText(MainActivity.this, "点击---通往天堂 code:"+code+" KeyEvent:"+keyEvent, Toast.LENGTH_SHORT).show();

//        returnfalse;

//    }

@OnEditorAction(R.id.tv_editor_action)

boolean EditTextAction(TextView textView,intcode, KeyEvent keyEvent) {

Toast.makeText(MainActivity.this, textView.getText().toString()+" 点击---通往天堂 code:"+code+" KeyEvent:"+keyEvent, Toast.LENGTH_SHORT).show();

returnfalse;

}

运行效果下:

dbab09c467ff75751f432d163f9bec91.gif

5. EditText内容改变监听事件

代码如下:

@OnTextChanged(value = R.id.editText, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)

void editTextChangeAfter(Editable editable) {

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)

void editTextChangeBefore(CharSequence s, 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)

void editTextChange(CharSequence s, intstart,intbefore,intcount) {

Toast.makeText(MainActivity.this, "编辑内容为:"+s+",开始前个数:"+start, Toast.LENGTH_SHORT).show();

System.out.println("未编辑---内容为:"+s+",开始前个数:"+start+","+before+","+count);

}

运行结果如下:

8d410533031658aa0e1a546574455271.png

6.焦点监听事件

代码如下:

@OnFocusChange(R.id.editTextFocus)

void editTextFocus(boolean isl) {

if (isl) {

Toast.makeText(MainActivity.this, "获取焦点"+ isl, Toast.LENGTH_SHORT).show();

} else{

Toast.makeText(MainActivity.this, "失去焦点"+ isl, Toast.LENGTH_SHORT).show();

}

}

运行结果如下:

fb681c563f2aaff994dacdd9e431cd76.gif

7. 触摸监听事件

代码如下:

@OnTouch(R.id.imageView)

boolean imageView(MotionEvent event){

System.out.println(event);

returnfalse;

}

运行结果如下:

04-10 11:47:04.504 32627-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)

void listItemClick(intposition){

Toast.makeText(this,"OnItemClick---点击了第"+position+"个",Toast.LENGTH_SHORT).show();

}

@OnItemLongClick(R.id.listView)

boolean listItemLongClick(intposition) {

Toast.makeText(this, "OnItemLongClick---点击了第"+ position +"个", Toast.LENGTH_SHORT).show();

returntrue;

}

运行结果如下:

7389cadd1454e237081b1bf2ed0def0c.gif

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

刀法二部曲,巧用Adapter

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

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="horizontal">

android:id="@+id/item_username"

android:layout_width="0dp"

android:layout_height="wrap_content"

android:layout_gravity="center_vertical"

android:layout_weight="1"/>

android:id="@+id/item_userPwd"

android:layout_width="0dp"

android:layout_height="wrap_content"

android:layout_gravity="center_vertical"

android:layout_weight="1"/>

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

package cn.hlq.butterknifestudy.adapter;

import android.content.Context;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.TextView;

import java.util.ArrayList;

import java.util.List;

import butterknife.BindView;

import butterknife.ButterKnife;

import cn.hlq.butterknifestudy.R;

import cn.hlq.butterknifestudy.model.Student;

/**

* Created byHLQon2017/4/11 0011.

*/

publicclass ListViewAdapter extends BaseAdapter {

private Context context;

private List stuList = new ArrayList();

publicListViewAdapter(Context context, List stuList) {

this.context = context;

this.stuList = stuList;

}

@Override

publicintgetCount() {

returnstuList !=null? stuList.size() : 0;

}

@Override

publicObject getItem(intposition) {

returnstuList !=null? stuList.get(position) :null;

}

@Override

publiclong getItemId(intposition) {

returnposition;

}

@Override

publicViewgetView(intposition,ViewconvertView, ViewGroup parent) {

ViewHolder viewHolder = null;

if (viewHolder == null) {

convertView = LayoutInflater.from(context).inflate(R.layout.item_listview_show,null);

viewHolder = new ViewHolder(convertView);

convertView.setTag(viewHolder);

} else{

viewHolder = (ViewHolder) convertView.getTag();

}

Student stu = stuList.get(position);

viewHolder.itemUsername.setText(stu.getUserName());

viewHolder.itemUserPwd.setText(stu.getUserPwd());

returnconvertView;

}

staticclass ViewHolder {

@BindView(R.id.item_username)

TextView itemUsername;

@BindView(R.id.item_userPwd)

TextView itemUserPwd;

ViewHolder(Viewview) {

ButterKnife.bind(this, view);

}

}

}

运行结果为:

3ecab36ca45441b41e5834a3d7da90e1.png

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

b69752e299e7b804e3b5ace56f36b049.png

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

// 初始化指定默认值

@BindString(R.string.app_test)

String titleContent;

lvTitle.setText(titleContent);

运行结果如下:

30d7c3e73e25ed2d230a27dd1f5f2783.png

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

4b297722345e809be4fd0a142bde8d4e.png

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

222aa9349ebfc5d915f8e86e9298b047.png

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

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

package com.heliquan.butterknife.base;

import android.app.Activity;

import android.content.Context;

import android.os.Bundle;

import android.support.annotation.LayoutRes;

import android.view.KeyEvent;

import android.view.View;

import android.view.ViewGroup;

import butterknife.ButterKnife;

import butterknife.Unbinder;

/**

* created byheliquanat2017年4月14日

*/

publicabstract class BaseActivity extends Activity {

private Unbinder unbinder;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

// 必须重写setContentView()的三个方法,不然会出现子类继承无效,具体原因没有深入了解

setContentView(getContentViewId());

unbinder = ButterKnife.bind(this);

}

@Override

publicvoid setContentView(@LayoutResintlayoutResID) {

super.setContentView(layoutResID);

unbinder = ButterKnife.bind(this);

}

@Override

publicvoid setContentView(Viewview) {

super.setContentView(view);

unbinder = ButterKnife.bind(this);

}

@Override

publicvoid setContentView(Viewview, ViewGroup.LayoutParams params) {

super.setContentView(view, params);

unbinder = ButterKnife.bind(this);

}

/**

* 获取内容id

*/

protected abstract intgetContentViewId();

/**

* 初始化View

*/

protected abstract void initView();

@Override

protected void onDestroy() {

super.onDestroy();

unbinder.unbind();

}

/**

* 根据id返回资源内容

*

* @param context

* @param strId

* @return

*/

protected String getStrResource(Activity activity, intstrId) {

returnactivity.getResources().getString(strId);

}

/**

* 监听返回按钮,点击返回finish当前页面

*

* @param keyCode

* @param event

* @return

*/

@Override

publicboolean onKeyDown(intkeyCode, KeyEvent event) {

if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {

finish();

returntrue;

}

returnsuper.onKeyDown(keyCode, event);

}

}

结束语

看到这里,想必大家已经基本对这套刀法有所了解以及能够基本运用了,感谢大家观看,如有不到之处,欢迎交流~

【编辑推荐】

【责任编辑:枯木 TEL:(010)68476606】

点赞 0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/291306.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nodejs的内存管理,垃圾回收机制

2019独角兽企业重金招聘Python工程师标准>>> 要点记录: 1、网页js、命令行工具,快进快出的,即时内存泄露,无内存管理必要! 2、服务器端nodejs和其他正规语言一样存在内存泄露。 3、nodejs基于谷歌v8js引擎&#xff…

Redis【第二篇】集群搭建

第一步:准备 1.安装包 ruby-2.4.0.tar.gz rubygems-2.6.10.tgz zlib-1.2.11.tar.gz redis-3.3.2.gem 2. 架构: 名称IP端口节点属性redisA192.168.6.1286379主节点redisB192.168.6.1289379从节点redisC192.168.6.1296379主节点redisD192.168.6.1299379从节…

(转)java中对集合对象list的几种循环访问总结

Java集合的Stack、Queue、Map的遍历在集合操作中,常常离不开对集合的遍历,对集合遍历一般来说一个foreach就搞定了,但是,对于Stack、Queue、Map类型的遍历,还是有一些讲究的。最近看了一些代码,在便利Map时…

NET框架下如何使用PaddleOCRSharp

打开VSIDE,新建Windows窗体应用(.NETFramework)类型的项目,选择一个.NET框架,如.NETFramework 4.0,右键点击项目,选择属性》生成,目标平台设置成X64.菜单》工具》选项,Nuget包管理器》程序包管理&#xff0…

Redis主从复制(Master-Slave Replication)

案例测试&#xff1a;1. Master新增网卡&#xff0c;修改server端配置IP : 192.168.40.128/24注释&#xff1a; bind&#xff0c;支持网络连接2. 新建虚机slave&#xff0c;配置网络&#xff0c;修改redis配置#slaveof <masterip> <masterport>slaveof 192.168.40.…

如何对一组 IP 地址 进行排序?

咨询区 Cracker我有一组如下IP地址。192.168.1.5 69.52.220.44 10.152.16.23 192.168.3.10 192.168.1.4 192.168.2.1我在寻找一个方法将他们排序成如下顺序。10.152.16.23 69.52.220.44 192.168.1.4 192.168.1.5 192.168.2.1回答区 Alex Aza对 ip 地址进行排序&#xff0c;大概…

如何为APK签名?

1.用来生成应用签名的文件①默认: debug.keystore > debug签名的应用程序不能在Android Market上架销售&#xff0c;它会强制你使用自己的签名。> 不同电脑使用此文件生成的签名不一样。那就意味着如果你换了机器进行apk版本升级&#xff0c;那么将会出现上面那种程序不能…

基于 Azure 的认知服务将文本合成语音

基于 Azure 的认知服务将文本合成语音Intro前几天发了一个 .NET 20 周年祝福视频&#xff0c;语音是通过 Azure 的认知服务合成的&#xff0c;下面就来介绍一下如何将使用 Azure 的认识服务实现将文本合成为语音Prepare你可以在 Azure Portal 上创建一个免费的语音服务&#xf…

sql查询结果集根据指定条件排序的方法

oracle认为 null 最大。 升序排列&#xff0c;默认情况下&#xff0c;null值排后面。 降序排序&#xff0c;默认情况下&#xff0c;null值排前面。 有几种办法改变这种情况&#xff1a; &#xff08;1&#xff09;用 nvl 函数或decode 函数 将null转换为一特定值 &#xff08;2…

mysql怎么改字体编码_mysql怎么改字符编码?

mysql命令行修改字符编码1、修改数据库字符编码mysql> alter database mydb character set utf8 ;2、创建数据库时&#xff0c;指定数据库的字符编码mysql> create database mydb character set utf8 ;3、查看mysql数据库的字符编码mysql> show variables like charac…

如何编译 dotnet/runtime 源代码

前言最近&#xff0c;准备为 dotnet/runtime 修改 issue&#xff0c;但是在 clone 代码后&#xff0c;发现要编译成功&#xff0c;远没有想象中那么容易。因此&#xff0c;将整个过程进行记录&#xff0c;以供大家参考。以下操作都是在 Windows 10 下完成。0.环境准备详见官方文…

jenkins maven testng selenium自动化持续集成

准备环境 首先我们新建一个maven的工程&#xff0c;并且在pom.xml中配置好我们依赖的一些jar包 <dependencies><dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>2.46.0<…

java程序 开发工具_15款Java程序员必备的开发工具

如果你是一名Web开发人员&#xff0c;那么用膝盖想也知道你的职业生涯大部分将使用Java而度过。这是一款商业级的编程语言&#xff0c;我们没有办法不接触它。对于Java&#xff0c;有两种截然不同的观点&#xff1a;一种认为Java是最简单功能***大的编程语言之一&#xff0c;另…

SQLite编译问题

从http://www.sqlite.org/主页上获得了SQLite的源文件&#xff0c;还没有时间研究就在编译上发生了不小的问题。 首先是碰到是&#xff0c;编译之后&#xff0c;只产生了sqlite3.dll文件&#xff0c;不产生对应的lib库文件。 查看了下sqlite3.h代码&#xff0c;发现了SQLITE_AP…

mysql的调试与分析_mysql日志管理分析调试实例_MySQL

以下的文章主要介绍的是MySQL 操作日志查看的实际操作步骤以及对其实际操作步骤的具体描述&#xff0c;假如你在实际操作中遇到相似的情况&#xff0c;但是你却不知道对其如何正确的解决&#xff0c;那么以下的文章对你而言一定是良师益友。刚接触MySQL不久&#xff0c;发现缺少…

.NET 7 预览版 1 发布

宣布 .NET 7 预览版 1Jeremy 2022 年 2 月 17 日今天&#xff0c;我们很高兴地宣布 .NET 历史上的下一个里程碑。在庆祝社区和 20 年创新的同时&#xff0c;.NET 7 Preview 1 标志着迈向 .NET 下一个 20 年的第一步。ASP.NET Core Preview 1 和 EF7 Preview 1 也在今天发布。.N…

你一写长文章就焦虑拖延?

这是病&#xff0c;得治。 症状 每年春季学期&#xff0c;总会有一些人很烦躁。 别人晒朋友圈&#xff0c;他留言说不中听的话&#xff1b;你见他突然妄自菲薄&#xff0c;开导劝慰他&#xff0c;却被辩驳甚至骂一通&#xff1b;一点儿小事儿&#xff0c;都能激起他胸中的愤怒&…

5.7.21mysql数据库_【数据库】mysql5.7.21 winx64安装配置图文分享

本文主要为大家详细介绍了mysql 5.7.21 winx64安装配置方法图文教程&#xff0c;具有一定的参考价值&#xff0c;感兴趣的小伙伴们可以参考一下&#xff0c;希望能帮助到大家。1、将下载好的mysql压缩包解压到安装目录下2、新建文件my.ini&#xff0c;放置到mysql安装目录下&am…

.NET7的七项重大改进!

.NET 7 Preview1发布了&#xff0c;没时间实操&#xff1f;先快来看看.NET7的七项重大改进&#xff01;1、不再支持.NET 7应用程序、运行时和SDK的多级查找&#xff08;MLL&#xff09;2、PATH停止向.NET 7运行时和SDK添加32位.NET3、默认情况下&#xff0c; dotnet build/publ…

Spring Boot 入门小目标 3 --- 先来试着热部署

2019独角兽企业重金招聘Python工程师标准>>> Spring Boot 入门小目标---先来试着热部署 这次写的主要就是 使用 springloaded 来实现 热部署。 很多时候&#xff0c;我们在修改和添加了新的方法或代码&#xff0c;都需要重启服务器。这样很麻烦&#xff0c;而且 不合…