<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                關于圖片加載,Flutter本身提供的Image Widget已經實現了加載網絡圖片的功能,且具備內存緩存的機制,我們看看Image的網絡圖片加載的實現。 ## Image的構造 ### 有參構造函數 ~~~ Image(Key key, @required this.image, …) ~~~ 開發者可根據自定義的ImageProvider來創建Image。 ### 命名構造函數 ~~~ Image.network(String src, …) ~~~ src即是根據網絡獲取的圖片url地址。 ~~~ Image.file(File file, …) ~~~ file指本地一個圖片文件對象,安卓中需要android.permission.READ_EXTERNAL_STORAGE權限。 ~~~ Image.asset(String name, …) ~~~ name指項目中添加的圖片資源名,事先在pubspec.yaml文件中有聲明。 ~~~ Image.memory(Uint8List bytes, …) ~~~ bytes指內存中的圖片數據,將其轉化為圖片對象。 ## ImageProvider `ImageProvider`一個抽象類,意思是圖片的提供者,主要是為Image控件提供圖片加載的邏輯,Image的有參構造函數里的image就是需要ImageProvider。 它的子類包括`NetworkImage`、`FileImage`、`ExactAssetImage`、`AssetImage`、`MemoryImage`等,網絡加載圖片使用的就是`NetworkImage`。 ## Image.network源碼分析 Image作為一個StatefulWidget其狀態由_ImageState控制,_ImageState繼承自State類,其生命周期方法包括initState()、didChangeDependencies()、build()、deactivate()、dispose()、didUpdateWidget()等。我們重點來_ImageState中函數的執行 ### _ImageState源碼分析 ~~~ @override void didChangeDependencies() { _updateInvertColors(); _resolveImage(); if (TickerMode.of(context)) _listenToStream(); else _stopListeningToStream(); super.didChangeDependencies(); } ~~~ #### _resolveImage `_updateInvertColors`就是設置了_invertColors的值,重點看看`_resolveImage` ~~~ void _resolveImage() { final ImageStream newStream = widget.image.resolve(createLocalImageConfiguration( context, size: widget.width != null && widget.height != null ? Size(widget.width, widget.height) : null, )); _updateSourceStream(newStream); } void _updateSourceStream(ImageStream newStream) { if (_imageStream?.key == newStream?.key) return; if (_isListeningToStream) _imageStream.removeListener(_getListener()); if (!widget.gaplessPlayback) setState(() { _imageInfo = null; }); setState(() { _loadingProgress = null; _frameNumber = null; _wasSynchronouslyLoaded = false; }); _imageStream = newStream; if (_isListeningToStream) _imageStream.addListener(_getListener()); } ~~~ 創建了一個`ImageStream`對象,該對象是一個圖片資源的句柄,其持有著圖片資源加載完畢后的監聽回調和圖片資源的管理者。 由于剛初始化_isListeningToStream為false,因此_updateSourceStream做的事情主要是把_imageStream設置成新創建的ImageStream。 #### _listenToStream 接著分析didChangeDependencies,后面會判斷TickerMode.of(context)的值,這個值默認是true,和AnimationConrol有關,后續可以深入研究。然后調用\_listenToStream()。 ~~~ void _listenToStream() { if (_isListeningToStream) return; _imageStream.addListener(_getListener()); _isListeningToStream = true; } ImageStreamListener _getListener([ImageLoadingBuilder loadingBuilder]) { loadingBuilder ??= widget.loadingBuilder; return ImageStreamListener( _handleImageFrame, onChunk: loadingBuilder == null ? null : _handleImageChunk, ); } void _handleImageFrame(ImageInfo imageInfo, bool synchronousCall) { setState(() { _imageInfo = imageInfo; _loadingProgress = null; _frameNumber = _frameNumber == null ? 0 : _frameNumber + 1; _wasSynchronouslyLoaded |= synchronousCall; }); } ~~~ 這里主要是向ImageStream對象中添加了監聽器\_handleImageChanged,監聽方法如下監聽方法最終回調用`setState`方法來通知界面刷新。 ### ImageProvider源碼分析 `ImageStream`對象是通過`widget.image.resolve`方法創建的,也就是對應`NetworkImage`的`resolve`方法,實現在`ImageProvider`類中找到了。 #### resolve ~~~ ImageStream resolve(ImageConfiguration configuration) { assert(configuration != null); final ImageStream stream = ImageStream(); T obtainedKey; final Zone dangerZone = Zone.current.fork( specification: ZoneSpecification( handleUncaughtError: (Zone zone, ZoneDelegate delegate, Zone parent, Object error, StackTrace stackTrace) { handleError(error, stackTrace); } ) ); dangerZone.runGuarded(() { Future<T> key; try { key = obtainKey(configuration); } catch (error, stackTrace) { handleError(error, stackTrace); return; } key.then<void>((T key) { obtainedKey = key; final ImageStreamCompleter completer = PaintingBinding.instance .imageCache.putIfAbsent(key, () => load(key), onError: handleError); if (completer != null) { stream.setCompleter(completer); } }).catchError(handleError); }); return stream; } ~~~ `ImageStreamCompleter`對象就是圖片資源的一個管理類。 ImageStream中的圖片管理者ImageStreamCompleter通過`PaintingBinding.instance.imageCache.putIfAbsent(key, () => load(key), onError: handleError);`方法創建,imageCache是Flutter框架中實現的用于圖片緩存的單例,查看其中的`putIfAbsent`方法 。 ## QA ### ImageProvider是啥 ## 參考資料 [Flutter Image全解析](https://www.jianshu.com/p/68879dd00f81)(Image詳細參數說明) [Flutter中網絡圖片加載和緩存](https://blog.csdn.net/weixin_43499085/article/details/88842438)(原理說明)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看