您的位置:首页 > 移动开发 > Android开发

详解Android中回调机制与RecyclerView的Item点击事件实现

2017-01-04 19:58 981 查看

总是看书上写着回调回调,以为就是函数调用换了个名字,尤其是看了Button的点击事件实现后,觉得不就是触发机制。

A事件发生->后台处理逻辑->告诉前台怎么做->结束。

Android常见button点击事件:

loginBtn = (Button) findViewById(R.id.login_button);
loginBtn.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(TestButtonActivity.this, "login", Toast.LENGTH_SHORT).show();

}
});


但其实回调不是这样的,完全不是!

这里由于使用了匿名内部类,机制是不很清晰,下面我们换成Activity实现接口的方式。

public class MainActivity extends Activity implements OnClickListener {

private Button bt;

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

bt = (Button) findViewById(R.id.bt);
bt.setOnClickListener(this);
}
  
  
  //用Activity实现OnClickListener接口
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Log.i("用Activity实现OnClickListener接口", "点击事件");
}

}


Button类继承自View类,View类处理点击事件。但是它并不具体指定如何处理,而是给出了接口OnClickListener规范

首先,Acticity这个类中持有Button类实例bt的引用,调用他的setOnClickListener()方法(实际还是View类的),传入了参数this,也就是这个Activity本身,希望View类处理点击事件。

然后,View类接受了请求,并利用传入的Activity类的引用,使用Avtivity类的 onClick()方法处理点击事件

这就是回调

就是A类中调用B类中的某个方法C,然后B类中反过来调用A类中的方法D,D这个方法就叫回调方法

这里D就是:

public void onClick(View v) {
// TODO Auto-generated method stub
Log.i("用Activity实现OnClickListener接口", "点击事件");
}


/**
* 这个View就相当于B类
*
*/
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
/**
* Call this view's OnClickListener, if it is defined.
*
* @return True there was an assigned OnClickListener that was called, false
*         otherwise is returned.
*/
public boolean performClick() {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);

if (mOnClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);

//B类(View类)调用A类Activity中click方法
mOnClickListener.onClick(this);
return true;
}

return false;
}
}


打印:Log.i(“用Activity实现OnClickListener接口”, “点击事件”);

也附上一个讲的很好的回调机制博客:回调机制

—————————————————————————————————————————————————————-

下面结合RecyclerView的点击事件实现实例,回顾一下。

RecyclerView是ListView的替代方案,十分的灵活,相比于ListView.难过的是它并没有像ListView一样提供setOnItemClickListener方法。他的点击事件都是由其中的viewholder中的view控件单独注册的,这样的好处是,如果再想实现某个列表项中的某个图标就十分简洁,不像以前ListView中那样麻烦。比如下面中的小三角播放按钮点击事件



但是这时候问题来了,我们想实现原来那样的整个列表项的点击事件怎么办?如:



要知道,现在点击事件都是在Adapter中由View自己注册的。如:

@Override
public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
View view=LayoutInflater.from(parent.getContext()).inflate(R.layout.category_item,parent,false);
final ViewHolder holder=new ViewHolder(view);
holder.cateImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position=holder.getAdapterPosition();
CateGory   categoryItem=mCateGoryList.get(position);
Toast.makeText(view.getContext(),"you click view"+categoryItem.getName(),Toast.LENGTH_SHORT).show();//工厂方法

}
});

return holder;
}


我们的思路是,每个列表项整个的点击事件就是ViewHolder被点击,所以让他自己注册自己的点击事件就好了。

首先,让ViewHolder实现View类的接口,能够处理自己的点击事件。

class ViewHolder extends  RecyclerView.ViewHolder implements View.OnClickListener {
ImageView cateImage;
TextView cateText;

public ViewHolder(View view){
super(view);
cateImage= (ImageView) view.findViewById(R.id.cate_image);
cateText= (TextView) view.findViewById(R.id.cate_name);
view.setOnClickListener(this);

}
@Override
public void onClick(View v) {
if (clickListener != null) {
clickListener.onClick(getAdapterPosition());

}
}
}


注意这已经是一层回调了。在ViewHolder和View之间的回调,clickListener是下面这个接口的实例,因为我们还需要一层回调。

在RecyclerView中定义好接口规范:

public static interface OnItemClickListener {
void onClick(int position);
}


再然后,我们希望在Activity中定义具体的处理逻辑,所以要把cliListener让外部实现,用方法暴露出去。

private OnItemClickListener clickListener;

public void setClickListener(OnItemClickListener clickListener) {
this.clickListener = clickListener;
}


在Activity的onCreate中实现:

adapter.setClickListener(new CateGoryAdapter.OnItemClickListener() {

@Override
public void onClick( int position) {
Toast.makeText(MainActivity.this,position+"",Toast.LENGTH_SHORT).show();
}
});


这里又是一层回调。在Activity和adapter之间。

写的不对的地方请告诉我谢谢!

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐