Flutter&Dart Callback轉(zhuǎn)同步

前言

怎么將一個Callback回調(diào)轉(zhuǎn)化成Future同步方法(Callback to Future),可以配套async / await去使用呢?

個人覺得,這是一個很常見的現(xiàn)象,不知道為啥,很多人在說明Future用法的時候,都沒提到這個場景,奇怪+懵逼,只能自己去茍解決方案了。

實(shí)現(xiàn)

不多嗶嗶,先看實(shí)現(xiàn),趕時間的靚仔,可以直接忽略掉歷程描述

  • 記錄下Callback to Future的寫法,使用Completer類即可
class ViewUtil {
  ///界面初始化完成
  static Future<Void> initFinish() async {
    Completer<Void> completer = Completer();

    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      completer.complete();
    });

    return completer.future;
  }
}
  • 使用
    • 使用起來,瞬間簡單很多
void _init() async {
    await ViewUtil.initFinish();
    ///下面可以使用加載彈窗
}

說明

  • Future<T>和Completer<T>的泛型最好保持一致
    • 例如都是String的話,complete()方法里面就可以加上相應(yīng)的內(nèi)容,然后await接受這個方法時候,就能拿到complete()方法里面輸入的值了
class ViewUtil {
    ///界面初始化完成
    static Future<String> initFinish() async {
        Completer<String> completer = Completer();

        WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
            completer.complete("測試一下...");
        });

        return completer.future;
    }
}


void _init() async {
    var s = await ViewUtil.initFinish();
    print(s);
}

歷程

  • 為什么我要將Callback轉(zhuǎn)成Future方法?
    • 大家知道,F(xiàn)lutter在加載頁面的時候,有個渲染的過程,在沒渲染完成的時候,你去顯示一些View的操作,會報錯的,例如:加載loading彈窗
    • 解決方法可能大家都知道,Lifecycle.initState / iniState 生命周期里面做個延時操作或者使用WidgetsBinding
//延時操作
await Future.delayed(Duration(milliseconds: 200));
//下面可以加載彈窗

//使用WidgetsBinding
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
    //此處可以加載彈窗
});
  • 當(dāng)然,使用WidgetsBinding是更靠譜和準(zhǔn)確的,但是這個Callback就讓我很方了,而且,這名字太長,也不太記的住,這就需要將它封裝了
  • 封裝WidgetsBinding
    • 蛋筒了,這玩意怎么封裝呢
class ViewUtil {
  ///界面初始化完成
  static Future<Void> initFinish() async {
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      
    });
  }
}
  • 首先我想到了:Future.delayed()
    • 進(jìn)去看下他的源碼
    • 有戲,可以看到,這里面明顯包含了一個Timer中的Callback回調(diào),但最后轉(zhuǎn)換成了,F(xiàn)uture方法
factory Future.delayed(Duration duration, [FutureOr<T> computation()?]) {
    if (computation == null && !typeAcceptsNull<T>()) {
        throw ArgumentError.value(
            null, "computation", "The type parameter is not nullable");
    }
    _Future<T> result = new _Future<T>();
    new Timer(duration, () {
        if (computation == null) {
            result._complete(null as T);
        } else {
            try {
                result._complete(computation());
            } catch (e, s) {
                _completeWithErrorCallback(result, e, s);
            }
        }
    });
    return result;
}
  • 分析下

    • 首先是實(shí)例化一個_Future<T>()對象,然后返回了這個_Future<T>()對象
    • 可以看到方法的最下方是直接返回這個對象,可想而知,這地方,肯定一直處于一個阻塞狀態(tài),在等待一個條件結(jié)束這個阻塞狀態(tài)
    • 然后在Timer的延遲時間到了后,其回調(diào)中使用了_complete()這個方法,這個方法應(yīng)該是結(jié)束了_Future<T>()對象的阻塞狀態(tài),然后再返回_Future<T>()對象,同時這個方法也結(jié)束了
  • 這不就簡單了,我把這個抄出來不就歐了

img
  • 這個_Future類是個私有方法,在future_impl.dart文件,把這個文件拷出來,放在我們工具類文件同一個包下,

    • 然后。。。
    image-20201023140910251
  • 這一堆報錯,玩毛線啊,肯定是我打開的方式不對

    • 難道要一個一個去解決這些報錯?要是這么麻煩,還搞毛線!
image-20201023144223906
  • 是不是我搜索的姿勢不對,再來搜搜看
    • 我去,還自動給我提示:dart callback to future,這么神奇的嗎?試試看
image-20201023143143286
img
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容