之前對(duì)接口回調(diào)一直有點(diǎn)模糊窿春,會(huì)寫但是理解的不透徹迂猴,今天記錄一下自己理解的回調(diào)是什么熏兄。
接口回調(diào)是什么秘狞?
接口回調(diào)是指:可以把使用某一接口的類創(chuàng)建的對(duì)象的引用賦給該接口聲明的接口變量躺屁,那么該接口變量就可以調(diào)用被類實(shí)現(xiàn)的接口的方法肯夏。實(shí)際上,當(dāng)接口變量調(diào)用被類實(shí)現(xiàn)的接口中的方法時(shí)犀暑,就是通知相應(yīng)的對(duì)象調(diào)用接口的方法驯击,這一過(guò)程稱為對(duì)象功能的接口回調(diào)。
這是什么鬼耐亏,抽象的一匹徊都,tmd能不能說(shuō)人話,不好意思激動(dòng)了
接下來(lái)我們先看一個(gè)例子琢磨一下:
Recyclerview是我們經(jīng)常用的广辰,但是它沒有像listview一樣提供OnItemClick方法暇矫,所以我們就自己去實(shí)現(xiàn),在Adapter定義Item點(diǎn)擊的回調(diào)接口择吊,定義回調(diào)方法李根,然后在合適的位置調(diào)用接口提供的方法(合適的位置:就是你想做操作的地方),再在Activity中實(shí)現(xiàn)這個(gè)Adapter中定義的接口几睛,復(fù)寫抽象方法房轿,關(guān)聯(lián)回調(diào)方法,然后你就可以在Activity中去做操作了(wc你說(shuō)的更含糊了,老子想抽你冀续,別急老鐵琼讽,下面用代碼看看)
public class AllPersonAdapter extends RecyclerView.Adapter<AllPersonAdapter.MyViewHolder> {
private Context context;
private ArrayList<UserList> allPerson;
private ItemOnClickInterface itemOnClickInterface;
public AllPersonAdapter(Context context, ArrayList<UserList> allPerson) {
this.context = context;
this.allPerson = allPerson;
}
//回調(diào)接口
private interface ItemOnClickInterface {
void onItemClick(View view, int position);
}
//定義回調(diào)方法
public void setItemOnClickInterface(ItemOnClickInterface itemOnClickInterface) {
this.itemOnClickInterface = itemOnClickInterface;
}
@Override
public AllPersonAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.recent_contacts_item, parent, false);
MyViewHolder myViewHolder = new MyViewHolder(view);
return myViewHolder;
}
@Override
public void onBindViewHolder(final AllPersonAdapter.MyViewHolder holder, int position) {
String name = allPerson.get(position).name;
if (name.length() >= 2) {
holder.peopleIcon.setText(name.substring(name.length() - 2, name.length()));
} else holder.peopleIcon.setText(name);
GradientDrawable bgShape = (GradientDrawable) holder.peopleIcon.getBackground();
bgShape.setColor(Color.parseColor(UiUtils.getRandColorCode()));
holder.peopleName.setText(name);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (itemOnClickInterface != null) {
int layoutPosition = holder.getLayoutPosition();
itemOnClickInterface.onClick(v, layoutPosition);
}
}
});
}
@Override
public int getItemCount() {
return allPerson == null ? 0 : allPerson.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView peopleIcon;
TextView peopleName;
public MyViewHolder(View itemView) {
super(itemView);
peopleIcon = (TextView) itemView.findViewById(R.id.icon_recent_contacts);
peopleName = (TextView) itemView.findViewById(R.id.name_recent_contacts);
}
}
}
看代碼更清楚些,首頁(yè)我們定義了一個(gè)ItemOnClickInterface的接口洪唐,接著寫了一個(gè)抽象方法用來(lái)監(jiān)聽钻蹬,監(jiān)聽什么呢?就是你做操作的時(shí)候比如點(diǎn)擊某一個(gè)按鈕我需要把相應(yīng)的數(shù)據(jù)回傳給調(diào)用這個(gè)接口的地方的過(guò)程凭需,可以有參也可以無(wú)參根據(jù)需求问欠,然后我們定義了一個(gè)回調(diào)方法,參數(shù)就是接口類型的粒蜈,接著定義一個(gè)變量來(lái)接收這個(gè)參數(shù)顺献,至此接口就定義完了。接下來(lái)我們就需要根據(jù)需求要什么我們給什么就可以了枯怖,上面代碼中我需要view和點(diǎn)擊時(shí)候的位置注整,好嘞給你傳過(guò)去不就完了。
看Activity中的代碼:
public class SubOrgOrDepActivity extends BaseActivity implements AllPersonAdapter.ItemOnClickInterface {
private AllPersonAdapter allPersonAdapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_suborg_or_dep);
allPersonAdapter = new AllPersonAdapter(this, allPersonList);
allPersonAdapter.setItemOnClickInterface(this); //通過(guò)回調(diào)方法將activity和adapter關(guān)聯(lián)上度硝,我們?cè)赼dapter中就可以通過(guò)activity去調(diào)用相應(yīng)的onItemClick方法了肿轨。
}
@Override
public void onItemClick(View v, int position) {
//TODO 這里就可以做操作了,view和位置都拿到了
}
}
看到這里是不是有點(diǎn)明白了,不明白沒有關(guān)系蕊程,通過(guò)上面這個(gè)例子我們整合一下回調(diào)接口該怎么做:
1椒袍、在需要傳遞數(shù)據(jù)的地方(類)定義一個(gè)接口,接口里面需要定義監(jiān)聽的方法以及參數(shù)
2藻茂、定義一個(gè)的接口類型的變量存儲(chǔ)數(shù)據(jù)驹暑。
3、定義一個(gè)公共的方法辨赐,讓外部去調(diào)用优俘,并且傳遞接口類型的參數(shù),給其定義的接口類型的數(shù)據(jù)初始化(就是初始化2中接口變量)
/**
* 定義一個(gè)接口
*/
public interface onListener{
void OnListener(String code,String msg);
}
/**
*定義一個(gè)變量?jī)?chǔ)存數(shù)據(jù)
*/
private onListener listener;
/**
*提供公共的方法,并且初始化接口類型的數(shù)據(jù)
*/
public void setListener( onListener listener){
this.listener = listener;
}
4掀序、在合適的位置調(diào)用接口里面的方法兼吓,傳遞數(shù)據(jù)。(比如點(diǎn)擊事件的地方)
/**
* 在合適的位置給其調(diào)用接口森枪,給其賦值
*/
@Override
public void onClick(View v) {
if (listener!=null) {
listener.OnListener(rtncode,rtnmsg);
}
}
5、在需要獲取數(shù)據(jù)的地方审孽,創(chuàng)建對(duì)象調(diào)方法县袱。
allPersonAdapter.setItemOnClickInterface(new AllPersonAdapter.ItemOnClickInterface() {
@Override
public void onClick(View v, int position) {
//在這里獲取數(shù)據(jù)進(jìn)行處理
}
});
實(shí)現(xiàn)接口的形式
1、定義一個(gè)接口佑力,可以另起包名式散,或者定義在類里面。
/**
* 定義一個(gè)接口
*/
public interface onListener{
void OnListener(String code,String msg);
}
2打颤、在需要傳遞數(shù)據(jù)的一端的構(gòu)造方法對(duì)接口進(jìn)行初始化暴拄。
public Print(OnListener listener) {
this.listener = listener;
}
3漓滔、在合適的位置調(diào)用接口里面的方法,傳遞數(shù)據(jù)乖篷。
/**
* 在合適的位置給其調(diào)用接口响驴,給其賦值
*/
if (listener!=null) {
listener.OnListener(rtncode,rtnmsg);
}
4、在需要獲取數(shù)據(jù)的地方創(chuàng)建對(duì)象傳遞參數(shù)撕蔼。
Print print = new Print(this);
這里面的this代指的是當(dāng)前頁(yè)面的activity豁鲤,如果是fragment的話,需要重寫onAttach方法對(duì)其進(jìn)行初始化鲸沮,強(qiáng)制類型轉(zhuǎn)換后獲取接口對(duì)象琳骡。此時(shí)在構(gòu)造方法里面?zhèn)鬟f接口得數(shù)據(jù)listener,如下二選一讼溺。
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
OnListener listener = (OnListener) activity;
}
@Override
public void onAttach(Context context) {
OnListener listener = (OnListener) activity;
}
注意:直接在fragment里面進(jìn)行獲取當(dāng)前fragment所在的activity楣号,調(diào)用getActivity進(jìn)行強(qiáng)轉(zhuǎn)或者直接傳遞會(huì)報(bào)錯(cuò)。報(bào)的錯(cuò)誤為類型轉(zhuǎn)換錯(cuò)誤怒坯。
5炫狱、讓activity實(shí)現(xiàn)此接口,重寫其抽象方法敬肚,在抽象法里面處理任務(wù)毕荐。
@Override
public void OnListener(String rtncode, String rtnmsg) {
//在這里獲取數(shù)據(jù)進(jìn)行處理
}
至此,接口回調(diào)講完了艳馒,通過(guò)代碼對(duì)回調(diào)有了一個(gè)大致的了解憎亚,好好琢磨一下感覺還是挺簡(jiǎn)單的。