接口回调听起来好像很厉害的样子,但其实只要能够搞清楚代码的执行过程,多看几遍,并且认真思考,再加上勤奋的练习,熟练掌握简单的接口回调并不是难题,接下来,我会用一个简单的例子,来带大家一起分析代码的执行过程,以及这样写的好处,以及这样写的思路。
我们知道recyclerView是没有自带点击事件的,所以这里我们就拿给recyclerView添加点击事件为例。
ok 我们做好了一个简单的recycerView,但是此时点击他的条目是无效的,接下来我们为他添加自己定义的条目点击事件。
在适配器中加入:
//自定义公开接口,定义抽象方法 public interface onItemClickListener{ void onItemClick(int position,View itemView); } //创建接口类型变量(接受传值并设置事件) private onItemClickListener mOnItemClickListener; //暴露设置接口的方法 public void setOnItemClickListener(onItemClickListener mOnItemClickListener){ this.mOnItemClickListener = mOnItemClickListener; }
在适配器的onBindViewHolder方法中开始监听事件:
@Override public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) { final MyViewHolder viewHolder = (MyViewHolder) holder; viewHolder.textView.setText(datas.get(position)); if (position % 2 == 0){ viewHolder.textView.setTextColor(Color.BLUE); }else { viewHolder.textView.setTextColor(Color.RED); } if (mOnItemClickListener != null){ viewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int pos = holder.getLayoutPosition(); mOnItemClickListener.onItemClick(pos,holder.itemView); } }); } }
最后一步就是在MainActivity中,实现onItemClickListener接口,设置监听,并实现抽象方法:
public class MainActivity extends AppCompatActivity implements MyAdapter.onItemClickListener
adapter.setOnItemClickListener(this);
@Override public void onItemClick(int position, View itemView) { Toast.makeText(MainActivity.this, "条目位置 :" + ( position + 1 ), Toast.LENGTH_SHORT).show(); }
OK,点击事件添加成功
很简单,很快,但是这个自己添加的点击事件,其中代码的执行过程大家清楚么?
按照代码的执行顺序,我们添加的代码第一句执行的就是:
adapter.setOnItemClickListener(this);这是调用了适配器设置监听的方法,this代表当前类,我们这里指的就是MainActivity,而这个方法定义的参数要求是一个我们自己定义的接口,所以我们要通过 MainActivity去实现OnItemClickListener接口,那么此时我们的MainActivity就也可以称作是OnItemClickListener类型。 将MainActivity传入后,就是将我们传入的值赋值给了自己定义的接口类型变量 //暴露设置接口的方法 public void setOnItemClickListener(onItemClickListener mOnItemClickListener){ this.mOnItemClickListener = mOnItemClickListener; }然后我们再来看一看这个自己定义的变量去做了什么: if (mOnItemClickListener != null){ viewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int pos = holder.getLayoutPosition(); mOnItemClickListener.onItemClick(pos,holder.itemView); } }); }
这是添加在onBindViewHolder中的,在调用了setOnItemClickListener方法后,mOnItemClickListener就不为空,然后当viewholder的条目点击之后,我们的mOnItemClickListener就调用了自己的onItemClick方法。
开始思考:我们这里的mOnItemClickListener不为空,那么他的值是哪里来的呢?是谁呢? 没有错,就是我们的MainActivity,那么这里调用了onItemClick方法,实际上调用的就是MainActivity中实现的抽象方法onItemClick
@Override public void onItemClick(int position, View itemView) { Toast.makeText(MainActivity.this, "条目位置 :" + ( position + 1 ), Toast.LENGTH_SHORT).show(); }
至此,我们得以解惑,只要在MainActivity中,实现一个接口,就实现了RecyclerView的点击事件,也了解了这个代码的执行过程,不过有人可能会疑惑,点击事件我直接写在适配器中不好吗,这样MainActivity中的代码不是会更少,更简洁吗?
好,根据质疑,我将代码做了如上修改,确实,点击事件依然好用,但是接口回调就没有作用吗?那还要他干嘛。好了,我要提出需求了。
如果我们的需求是点击了一条目之后,修改MainActivity中一个控件(例如Button)的背景颜色,想一想,此时怎么操作?
可能还真有头铁的愣头青会说:可以在MainActivity中通过适配器的构造方法,把控件(例如Button)对象传到Adapter里面,很好,很有思想。但是我这里首先不说你违背了通俗的编程习惯(我没怎么见过把一个控件对象传来传去的),如果我要有100个控件要改变呢?
显然 100个夸张了一点,但是基本的设计模式,我们还是要遵循的,所以接口回调的好处,大家体会到了吗?
Demo下载