詳解Android中回撥機制與RecyclerView的Item點選事件實現
阿新 • • 發佈:2019-01-08
總是看書上寫著回調回調,以為就是函式呼叫換了個名字,尤其是看了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();
}
});