淺析回調機制,這是一篇騷騷的文章

序:

先給一個,我對回調機制的認識:回調就是我不知道你調用這個  具體  幹嗎,可是我知道你  大概  要幹嗎android

好比點擊,寫源碼的人不知道點擊按鈕以後登錄,仍是彈出對話框,可是寫源碼的人知道按鈕加載出來而且人的手觸摸並擡起這個動做就是點擊。

咱們先不看android的點擊事件,咱們先本身作一個回調。程序員

第一章: 校長要去開會

想象一個場景(鄭重承諾,本例不針對任何一我的,只是舉例,若是引發不適,請關閉)bash

你們都上過學,學校的boss假設就是 校長 ,校長的工做是管理同窗們好好學習,快樂成長。可是一個校長管理不過來好幾千名學生,因此要把工做分給 班主任教導處主任網絡

一個學校總有那麼幾個調皮搗蛋的學生,那麼校長就得管管,管的方式假設有兩種說(talk)和打(fuck),可是校長沒時間,由於校長去開會了,就把任務交給班主任和教導處主任有可能還有別的老師。好了,校長在走以前先定義好了說和打的模塊。app

package TestCallBack;
/**
 * 校長類(關於類名個人英文水平就這樣,愛看不看)
 * @author Robin
 *
 */
public class XiaoZhang {

    //工做的引用
    DoJob mDoJob;

    //定義工做類型
    public interface DoJob {
        void talk(String teacherName);//說

        void fuck(String teacherName, String tool);//打
    }

    //對外暴露調用位置
    public void setmDoJobCallBack(String teacherName, String tool, DoJob doJob) {
        if (doJob != null) {
            doJob.talk(teacherName);//工做是-->說
            doJob.fuck(teacherName, tool);//工做是-->打
        }
    }

}
複製代碼

第二章:校長走了,學生炸了,老師火了

校長走後,同窗們隨心所欲,班主任見狀不妙,立刻開始工做。eclipse

package TestCallBack;

import TestCallBack.XiaoZhang.DoJob;

/**
 * 班主任
 * 
 * @author Robin
 * 
 */
public class ClassTeacher implements DoJob {

    public void talk(String teacherName) {
        // 班主任開始跟學生交談
        System.out.println("班主任 "+teacherName + " 開始口頭教育學生");
    }

    public void fuck(String teacherName, String tool) {
        // 班主任開始幹學生
        System.out.println("班主任 "+teacherName + " 開始用 " + tool + " 打學生");
    }

}
複製代碼

(聲明,咱們不提倡打學生)ide

班主任:喂,校長嗎?我要管學生了
校長:好
因而校長就new 了一個對象,並把班主任傳進來,讓班主任管學生函數

XiaoZhang xz = new XiaoZhang();// 建立一個校長
xz.setmDoJobCallBack("李二狗", "教鞭", new ClassTeacher());
複製代碼

log打印以下:(用eclipse怎麼了?誰不是從ec過來的。。。)
這裏寫圖片描述
工具

教導主任管理學生同理:
學習

package TestCallBack;

import TestCallBack.XiaoZhang.DoJob;

/**
 * 教導處主任
 * 
 * @author Robin
 * 
 */
public class JaoDaoChuTeacher implements DoJob {
    public void talk(String teacherName) {
        // 教導處主任開始跟學生聊天
        System.out.println("教導處主任 " + teacherName + " 開始口頭教育學生");
    }

    public void fuck(String teacherName, String tool) {
        // 教導處主任開始打學生
        System.out
                .println("教導處主任 " + teacherName + " 開始用 " + tool + " 打學生");
    }

}
複製代碼

建立對象,並執行

XiaoZhang xz = new XiaoZhang();// 建立一個校長
xz.setmDoJobCallBack("蒙哥·卡恩", "斧頭", new JaoDaoChuTeacher());
複製代碼

log打印以下:
這裏寫圖片描述

這個地方注意,若是我想改寫教導主任的talk,fuck方法,怎麼寫?

xz.setmDoJobCallBack("蒙哥·卡恩", "斧頭", new JaoDaoChuTeacher(){

            @Override
            public void talk(String teacherName) {
//              super.talk(teacherName);
                System.out.println(teacherName);//只打印教導主任的名字
            }

            @Override
            public void fuck(String teacherName, String tool) {
                super.fuck(teacherName, tool);//又想執行被教導主任打的方法
                System.out.println("被教導主任請去喝茶嗑瓜子");//打完以後又喝茶嗑瓜子
            }

        });
複製代碼

注意super,調用父類的方法。
打印以下:
這裏寫圖片描述

第三章:校長回來了

校長髮現,效果並很差,學生仍是很皮,因而,校長又另請高明,既不是教導處主任,也不是班主任,是一個新的角色,他叫robin,擅長用皮鞭,怎麼寫?
首先確定是要有一個校長的贊成,因此須要建立一個校長對象

XiaoZhang xz = new XiaoZhang();// 建立一個校長
xz.setmDoJobCallBack("robin", "皮鞭", new DoJob() {//注意這個地方是DoJob

            public void talk(String teacherName) {
                // TODO Auto-generated method stub
                System.out.println(teacherName + " 和我談話了");
            }

            public void fuck(String teacherName, String tool) {
                // TODO Auto-generated method stub
                System.out.println("艾媽,我被 " + teacherName + " 用 " + tool
                        + " 打了");
            }
        });
複製代碼

log:
這裏寫圖片描述

完結。

最後讓咱們再來審視一下,開頭我提出來的

回調就是我不知道你調用這個 具體 幹嗎,可是我知道你 大概 要幹什麼。

校長讓座這個管理學生的工做,校長不知道具體是誰來作,怎麼作,可是校長知道管學生有說和打兩種方式。這個 就是所謂的 回調函數

你覺得結束了?看看右邊滾動條吧,孩子。這是開始,前面都是鋪墊。(Java程序員適當翻看下面內容。)
問題來了,回調有個J8用?

最先開始,你們都知道我請求網絡數據,通常都有兩個回調方法
onSuccess
onFailed
沒錯,我就是用xUtils長大的。
上網查閱資料以後,這裏用到的網絡回調僞代碼大概以下:

public static void sendHttpRequest(final String address,
            final HttpCallbackListener listener) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                try {
                ...//這裏用HttpUrlConnection取到數據
                    while ((line = reader.readLine()) != null) {//流轉換,獲得字符串
                        response.append(line);
                    }
                    if (listener != null) {
                        // 回調onSuccess()方法,攜帶數據
                        listener.onSuccess(response.toString());
                    }
                } catch (Exception e) {
                    if (listener != null) {
                        // 回調onFailed()方法,攜帶報錯信息
                        listener.onFailed(e);
                    }
                } finally {
                    if (connection != null) {
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }
複製代碼

我以前也是似懂非懂,如今感受明白了很多。

你覺得完了?
android用到了不少回調機制,好比按鈕的點擊事件、線程的run()方法
下面開始講Android裏面的回調機制。 

這篇文章不錯,我引用一下,做者不要打我
juejin.im/entry/58c23…

裏面說到這兩個例子
1. 給RecyclerView的item添加點擊事件

public class ClickAdapter extends RecyclerView.Adapter{
    //定義接口實例
    private OnClickItemListener mOnClickItemListener;

    //設置接口實例的setter方法
    public void setOnClickItemListener(OnClickItemListener onClickItemListener) {
        mOnClickItemListener = onClickItemListener;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { . . . }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) { . . . }

    @Override
    public int getItemCount() { . . . }

    public class ViewHolder extends RecyclerView.ViewHolder{
        // ...
        // 視圖控件初始化
        public ViewHolder(View itemView) { . . . }
        /*綁定視圖方法,在Adapter的onBindViewHolder中調用*/
        public void bindHolder(final String text) {
            mTextView.setText(text);
            if (null != mOnClickItemListener) {
                itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        //在點擊事件中進行回調
                        mOnClickItemListener.onClick(text);
                    }
                });
            }
        }
    }
    //建立內部接口
    interface OnClickItemListener{
        void onClick(String text);
    }
}
複製代碼

因此,接口回調能夠總結爲如下4步:

  • 建立內部接口
  • 定義接口實例
  • 設置接口實例的setter方法
  • 在點擊事件中進行回調

2.用子線程加載網絡圖片,並顯示在主線程中

public class ImageUtil {
    public static void loadeIamge(final String url, final LoadeImageListener listener) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                InputStream is = null;
                BufferedInputStream bis = null;
                try {
                    HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
                    connection.setConnectTimeout(5000);
                    connection.connect();
                    is = connection.getInputStream();
                    bis = new BufferedInputStream(is);
                    //拿到bitmap,通知(調用)onLoadeImageListener。
                    listener.onLoadeImageListener(BitmapFactory.decodeStream(bis));
                } catch (Exception e) {
                    e.printStackTrace();
                }finally {
                    CloseUtil.closeQuietly(is);
                    CloseUtil.closeQuietly(bis);
                }
            }
        }).start();
    }
    public interface LoadeImageListener {
         void onLoadeImageListener(Bitmap bitmap);
     }
}
複製代碼

上面的代碼就是一個加載網絡圖片的工具類,能夠發如今這裏,沒有定義接口實例,也沒有定義接口實例的setter方法,而是直接用調用者那裏傳來的接口實例進行操做。

下面來看看調用者的實現:

final ImageView imageView = (ImageView) findViewById(R.id.image_view);
       ImageUtil.loadeIamge(IMG_URL, new ImageUtil.LoadeImageListener() {
           @Override
           public void onLoadeImageListener(Bitmap bitmap) {
               imageView.setImageBitmap(bitmap);
           }
       });
複製代碼

完。喜歡的點個贊,你的支持是我最大的動力。

本站公眾號
   歡迎關注本站公眾號,獲取更多信息