欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Flutter加載圖片流程之ImageProvider源碼示例解析

 更新時間:2023年04月20日 11:38:13   作者:Nicholas68  
這篇文章主要為大家介紹了Flutter加載圖片流程之ImageProvider源碼示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

加載網(wǎng)絡圖片

Image.network()是Flutter提供的一種從網(wǎng)絡上加載圖片的方法,它可以從指定的URL加載圖片,并在加載完成后將其顯示在應用程序中。本節(jié)內(nèi)容,我們從源碼出發(fā),探討下圖片的加載流程。

ImageProvider

ImageProvider是Flutter中一個抽象類,它定義了一種用于加載圖片的通用接口,可以用于加載本地圖片、網(wǎng)絡圖片等各種類型的圖片。

ImageProvider類包含兩個核心方法:obtainKeyloadBuffer。

resolve

/// Resolves this image provider using the given `configuration`, returning
/// an [ImageStream].
///
/// This is the public entry-point of the [ImageProvider] class hierarchy.
///
/// Subclasses should implement [obtainKey] and [load], which are used by this
/// method. If they need to change the implementation of [ImageStream] used,
/// they should override [createStream]. If they need to manage the actual
/// resolution of the image, they should override [resolveStreamForKey].
///
/// See the Lifecycle documentation on [ImageProvider] for more information.
@nonVirtual
ImageStream resolve(ImageConfiguration configuration) {
  assert(configuration != null);
  final ImageStream stream = createStream(configuration);
  // Load the key (potentially asynchronously), set up an error handling zone,
  // and call resolveStreamForKey.
  _createErrorHandlerAndKey(
    configuration,
    (T key, ImageErrorListener errorHandler) {
      resolveStreamForKey(configuration, stream, key, errorHandler);
    },
    (T? key, Object exception, StackTrace? stack) async {
      await null; // wait an event turn in case a listener has been added to the image stream.
      InformationCollector? collector;
      assert(() {
        collector = () => <DiagnosticsNode>[          DiagnosticsProperty<ImageProvider>('Image provider', this),          DiagnosticsProperty<ImageConfiguration>('Image configuration', configuration),          DiagnosticsProperty<T>('Image key', key, defaultValue: null),        ];
        return true;
      }());
      if (stream.completer == null) {
        stream.setCompleter(_ErrorImageCompleter());
      }
      stream.completer!.reportError(
        exception: exception,
        stack: stack,
        context: ErrorDescription('while resolving an image'),
        silent: true, // could be a network error or whatnot
        informationCollector: collector,
      );
    },
  );
  return stream;
}

根據(jù)文檔解釋,我們可以了解到以下幾點:

1、使用給定的`configuration`解析該圖片提供器,返回一個 [ImageStream]。  

2、這是 [ImageProvider] 類層次結構的公共入口點。

3、子類應該實現(xiàn) [obtainKey] 和 [load] 方法,這兩個方法將被該方法使用。 

4、如果子類需要更改使用的 [ImageStream] 的實現(xiàn),則應該重寫 [createStream] 方法。 

5、 如果子類需要管理實際的圖像分辨率,則應該重寫 [resolveStreamForKey] 方法。 

閱讀resolve方法的實現(xiàn)。我們可以知道:

1、它使用給定的configuration參數(shù)創(chuàng)建一個ImageStream對象(createStream)。然后調用_createErrorHandlerAndKey方法,該方法會異步獲取圖片的唯一標識符,并設置一個錯誤處理區(qū)域,以防圖片加載過程中發(fā)生錯誤。

2、如果獲取唯一標識符的過程中出現(xiàn)異常,則會將錯誤信息封裝成一個_ErrorImageCompleter對象,并將其設置為ImageStreamcompleter屬性,表示圖片加載失敗。

3、如果唯一標識符獲取成功,則會調用resolveStreamForKey方法來解析圖片,并將圖片數(shù)據(jù)存儲到ImageStream對象中,供后續(xù)使用。

4、該方法是ImageProvider類層次結構的公共入口點,因為它是所有圖片提供器的解析方法。子類只需要實現(xiàn)obtainKeyload方法來獲取圖片的唯一標識符和加載圖片的數(shù)據(jù),而不需要重寫resolve方法。

5、如果子類需要更改使用的ImageStream的實現(xiàn)方式,則可以重寫createStream方法。如果子類需要管理實際的圖像分辨率,則可以重寫resolveStreamForKey方法。例如,AssetImage類中的createStream方法返回一個AssetBundleImageStreamCompleter對象,該對象用于從應用程序資源中加載圖片數(shù)據(jù)。而NetworkImage類中的resolveStreamForKey方法使用HTTP客戶端從網(wǎng)絡上加載圖片數(shù)據(jù)。

6、這段代碼中還有一些調試信息,例如將圖片提供器、圖片配置和圖片唯一標識符添加到調試信息中,以便在出現(xiàn)錯誤時進行調試。

obtainKey

/// Converts an ImageProvider's settings plus an ImageConfiguration to a key
/// that describes the precise image to load.
///
/// The type of the key is determined by the subclass. It is a value that
/// unambiguously identifies the image (_including its scale_) that the [load]
/// method will fetch. Different [ImageProvider]s given the same constructor
/// arguments and [ImageConfiguration] objects should return keys that are
/// '==' to each other (possibly by using a class for the key that itself
/// implements [==]).
Future&lt;T&gt; obtainKey(ImageConfiguration configuration);

這段注釋是關于obtainKey方法的說明。該方法是ImageProvider的子類應該實現(xiàn)的方法之一,用于將ImageProvider的設置及ImageConfiguration轉換為一個可以唯一標識圖片的key

不同的ImageProvider根據(jù)相同的構造函數(shù)參數(shù)和ImageConfiguration對象應該返回相等的key,以便于后續(xù)加載和緩存圖片。key的類型由子類確定,它應該是一個值,可以唯一地標識出要加載的圖片(包括其縮放比例)。

在實現(xiàn)obtainKey方法時,子類可以考慮使用自定義的類來表示key,并實現(xiàn)==方法以保證唯一性。

resolveStreamForKey

@protected
void resolveStreamForKey(ImageConfiguration configuration, ImageStream stream, T key, ImageErrorListener handleError) {
  // This is an unusual edge case where someone has told us that they found
  // the image we want before getting to this method. We should avoid calling
  // load again, but still update the image cache with LRU information.
  if (stream.completer != null) {
    final ImageStreamCompleter? completer = PaintingBinding.instance.imageCache.putIfAbsent(
      key,
      () => stream.completer!,
      onError: handleError,
    );
    assert(identical(completer, stream.completer));
    return;
  }
  final ImageStreamCompleter? completer = PaintingBinding.instance.imageCache.putIfAbsent(
    key,
    /// 加載
    () => loadBuffer(key, PaintingBinding.instance.instantiateImageCodecFromBuffer),
    onError: handleError,
  );
  if (completer != null) {
    /// 關鍵是解析并設置ImageStreamCompleter對象
    stream.setCompleter(completer);
  }
}

官方文檔解釋:

  • 該方法是ImageProvider的子類應該實現(xiàn)的方法之一,用于根據(jù)key來解析圖片。
  • resolveStreamForKey方法是由resolve方法調用的,其參數(shù)包括ImageConfiguration、ImageStream、keyerrorHandler。子類可以通過實現(xiàn)resolveStreamForKey方法來管理圖片的實際解析過程,同時也可以通過調用errorHandler來處理解析過程中可能發(fā)生的錯誤。
  • 實現(xiàn)resolveStreamForKey方法時,子類可以考慮使用keyImageCache交互,例如調用ImageCache.putIfAbsent方法,并向stream通知監(jiān)聽器。默認實現(xiàn)已經(jīng)使用keyImageCache交互,子類可以選擇調用super.resolveStreamForKey方法或不調用。

從上面的源碼,我們可以知道以下幾點:

  • 1、如果 stream 對象已經(jīng)有了 completer(即已經(jīng)有了可以加載圖片的方式),則將 completer 添加到 ImageCache 中,實現(xiàn)緩存功能,并直接返回。
  • 2、如果 stream 對象還沒有 completer,則調用 loadBuffer 方法加載圖片,并將其返回的 ImageStreamCompleter 對象添加到 ImageCache 中,同時設置到 stream 對象的 completer 中。
  • 3、如果 loadBuffer 方法出現(xiàn)了異常,則會將異常交給 onError 回調處理,以便在異常處理時能夠提供詳細的錯誤信息。
  • 4、關鍵是解析并設置ImageStreamCompleter對象
  • 5、PaintingBinding.instance.imageCache.putIfAbsent方法在內(nèi)部將ImageStreamListener對象添加到ImageStreamCompleter對象的_listeners數(shù)組中了。
   PaintingBinding.instance.imageCache.putIfAbsent(
     key,
     () =&gt; loadBuffer(key, PaintingBinding.instance.instantiateImageCodecFromBuffer),
     onError: handleError,
   )

loadBuffer

/// Converts a key into an [ImageStreamCompleter], and begins fetching the
/// image.
///
/// For backwards-compatibility the default implementation of this method calls
/// through to [ImageProvider.load]. However, implementors of this interface should
/// only override this method and not [ImageProvider.load], which is deprecated.
///
/// The [decode] callback provides the logic to obtain the codec for the
/// image.
///
/// See also:
///
///  * [ResizeImage], for modifying the key to account for cache dimensions.
@protected
ImageStreamCompleter loadBuffer(T key, DecoderBufferCallback decode) {
  return load(key, PaintingBinding.instance.instantiateImageCodec);
}

從源碼我們知道, [ImageProvider.load], which is deprecated被廢棄了。子類只需要重寫loadBuffer方法即可。

  • 這個方法是ImageProvider的一個protected方法,用于從緩存中加載指定的圖片。
  • 它接受兩個參數(shù):一個是唯一標識圖片的key,另一個是一個用于解碼圖片數(shù)據(jù)的回調函數(shù)decode。
  • 這個方法調用了load方法,然后返回一個ImageStreamCompleter對象,它表示加載過程中的一個數(shù)據(jù)流。
  • 在load方法中,使用傳入的decode回調函數(shù)從緩存或網(wǎng)絡中獲取圖片數(shù)據(jù)并解碼,然后將解碼后的圖片數(shù)據(jù)傳遞給ImageStreamCompleter對象,以便它可以生成一個帶有正確圖片數(shù)據(jù)的ImageInfo對象,這個ImageInfo對象可以被傳遞到Image widget中用于顯示圖片。

load(被廢棄)

/// Converts a key into an [ImageStreamCompleter], and begins fetching the
/// image.
///
/// This method is deprecated. Implement [loadBuffer] for faster image
/// loading. Only one of [load] and [loadBuffer] must be implemented, and
/// [loadBuffer] is preferred.
///
/// The [decode] callback provides the logic to obtain the codec for the
/// image.
///
/// See also:
///
///  * [ResizeImage], for modifying the key to account for cache dimensions.
@protected
@Deprecated(
  'Implement loadBuffer for faster image loading. '
  'This feature was deprecated after v2.13.0-1.0.pre.',
)
ImageStreamCompleter load(T key, DecoderCallback decode) {
  throw UnsupportedError('Implement loadBuffer for faster image loading');
}

從注釋可知:

這個方法被廢棄了,現(xiàn)在已經(jīng)不再建議使用了。如果需要更快的圖像加載,請實現(xiàn) [loadBuffer] 方法。在 [load] 和 [loadBuffer] 方法中只需要實現(xiàn)其中一個,而且 [loadBuffer] 更受推薦。

[decode] 回調提供了獲取圖像編解碼器的邏輯。

evict

/// Evicts an entry from the image cache.
///
/// Returns a [Future] which indicates whether the value was successfully
/// removed.
///
/// The [ImageProvider] used does not need to be the same instance that was
/// passed to an [Image] widget, but it does need to create a key which is
/// equal to one.
///
/// The [cache] is optional and defaults to the global image cache.
///
/// The [configuration] is optional and defaults to
/// [ImageConfiguration.empty].
///
/// {@tool snippet}
///
/// The following sample code shows how an image loaded using the [Image]
/// widget can be evicted using a [NetworkImage] with a matching URL.
///
/// ```dart
/// class MyWidget extends StatelessWidget {
///   const MyWidget({
///     super.key,
///     this.url = ' ... ',
///   });
///
///   final String url;
///
///   @override
///   Widget build(BuildContext context) {
///     return Image.network(url);
///   }
///
///   void evictImage() {
///     final NetworkImage provider = NetworkImage(url);
///     provider.evict().then&lt;void&gt;((bool success) {
///       if (success) {
///         debugPrint('removed image!');
///       }
///     });
///   }
/// }
/// ```
/// {@end-tool}
Future&lt;bool&gt; evict({ ImageCache? cache, ImageConfiguration configuration = ImageConfiguration.empty }) async {
  cache ??= imageCache;
  final T key = await obtainKey(configuration);
  return cache.evict(key);
}

這是一個名為evict的異步方法,它的作用是從圖像緩存中刪除給定配置下的圖片。它有兩個可選參數(shù):cacheconfiguration。如果cache參數(shù)為null,則默認使用全局的imageCache。configuration參數(shù)是一個圖像配置,它用于獲取將要從緩存中刪除的圖片的鍵值。這個方法返回一個Future<bool>對象,表示刪除是否成功。如果緩存中沒有找到要刪除的圖片,則返回false。

列表快速滑動,內(nèi)存暴增時,可以用這個方法做些事情。

總結

ImageProvider是Flutter中一個用于提供圖像數(shù)據(jù)的抽象類,它定義了如何從不同的數(shù)據(jù)源(如文件系統(tǒng)、網(wǎng)絡、內(nèi)存)中獲取圖像數(shù)據(jù),并將其轉換成ImageStreamCompleter對象,以供Image組件使用。

在Flutter中,使用Image組件來加載和顯示圖像,需要先提供一個ImageProvider對象作為其image屬性的值。ImageProvider類包含了兩個關鍵的方法:obtainKeyload。

obtainKey方法用于獲取一個用于唯一標識圖像數(shù)據(jù)的ImageProvider對象,這個對象可以用來緩存圖像數(shù)據(jù),以便在需要重新加載圖像時能夠快速獲取到它。例如,AssetImage類使用圖片資源的路徑作為其ImageProvider對象的標識符,以便在需要重新加載該資源時能夠快速地從內(nèi)存或磁盤緩存中獲取到它。

load方法用于獲取一個ImageStreamCompleter對象,該對象包含了用于繪制圖像的圖像數(shù)據(jù)。在Flutter 2.5之前,load方法是一個抽象方法,必須由子類實現(xiàn)。但是從Flutter 2.5開始,load方法已被廢棄,取而代之的是resolve方法。resolve方法接受一個ImageConfiguration參數(shù),并返回一個Future<ImageStreamCompleter>對象。它與load方法的功能類似,都是用于獲取圖像數(shù)據(jù),并將其轉換成ImageStreamCompleter對象,以供Image組件使用。

使用ImageProvider類加載和顯示圖像的流程如下:

  • 創(chuàng)建一個ImageProvider對象,該對象提供了圖像數(shù)據(jù)的來源和標識符。
  • 使用ImageProvider對象作為Image組件的image屬性的值。
  • Image組件會調用obtainKey方法獲取一個用于唯一標識圖像數(shù)據(jù)的ImageProvider對象。
  • Image組件會調用resolve方法獲取一個Future<ImageStreamCompleter>對象。
  • 當圖像數(shù)據(jù)加載完成后,ImageStreamCompleter對象會將其通知給Image組件,Image組件會將其渲染到屏幕上。

總的來說,ImageProvider類是Flutter中一個非常重要的類,它提供了一種方便的方式來加載和顯示圖像。雖然load方法已被廢棄,但是resolve方法提供了更好的替代方案,可以用于獲取圖像數(shù)據(jù)并將其轉換成ImageStreamCompleter對象。

參考鏈接

Flutter系統(tǒng)網(wǎng)絡圖片加載流程解析_Android

Flutter入門系列(四)---Flutter圖片緩存

Flutter | Image 源碼分析與優(yōu)化方式

困惑解答

第一次加載圖片時,stream對象通常沒有completer。在第一次調用resolveStreamForKey時,會將stream對象的completer與對應的ImageCacheImageStreamCompleter進行綁定,并且completer會被設置為ImageStreamCompleter

以上就是Flutter加載圖片流程之ImageProvider源碼示例解析的詳細內(nèi)容,更多關于Flutter加載圖片ImageProvider的資料請關注腳本之家其它相關文章!

相關文章

  • Android開發(fā)手冊Button按鈕實現(xiàn)點擊音效

    Android開發(fā)手冊Button按鈕實現(xiàn)點擊音效

    這篇文章主要為大家介紹了Android開發(fā)手冊Button按鈕實現(xiàn)點擊音效示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • Android App調用MediaRecorder實現(xiàn)錄音功能的實例

    Android App調用MediaRecorder實現(xiàn)錄音功能的實例

    這篇文章主要介紹了Android App調用MediaRecorder實現(xiàn)錄音功能的實例,MediaRecorder非常強大,不僅能夠用來錄制音頻還可以錄制視頻,需要的朋友可以參考下
    2016-04-04
  • Android中SwipeBack實現(xiàn)右滑返回效果

    Android中SwipeBack實現(xiàn)右滑返回效果

    這篇文章主要介紹了Android中SwipeBack實現(xiàn)右滑返回效果的相關資料,需要的朋友可以參考下
    2016-02-02
  • RecyclerView+PagerSnapHelper實現(xiàn)抖音首頁翻頁的Viewpager效果

    RecyclerView+PagerSnapHelper實現(xiàn)抖音首頁翻頁的Viewpager效果

    這篇文章主要為大家詳細介紹了RecyclerView+PagerSnapHelper實現(xiàn)抖音首頁翻頁的Viewpager效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • Android端權限隱私的合規(guī)化處理實戰(zhàn)記錄

    Android端權限隱私的合規(guī)化處理實戰(zhàn)記錄

    大家應該都發(fā)現(xiàn)了,現(xiàn)在很多應用市場都要求應用上架需要用戶協(xié)議,這篇文章主要給大家介紹了關于Android端權限隱私合規(guī)化處理的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2021-08-08
  • Flutter中獲取屏幕及Widget的寬高示例代碼

    Flutter中獲取屏幕及Widget的寬高示例代碼

    這篇文章主要給大家介紹了關于Flutter中如何獲取屏幕及Widget的寬高的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者使用Flutter具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-03-03
  • 詳解Android布局加載流程源碼

    詳解Android布局加載流程源碼

    這篇文章主要介紹了詳解Android布局加載流程源碼,對布局感興趣的同學可以參考下
    2021-04-04
  • Android開發(fā)Compose remember原理解析

    Android開發(fā)Compose remember原理解析

    這篇文章主要為大家介紹了Android開發(fā)Compose remember原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • Android仿手機QQ圖案解鎖功能

    Android仿手機QQ圖案解鎖功能

    這篇文章主要為大家詳細介紹了Android仿手機QQ圖案解鎖功能的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Android幀率監(jiān)測與優(yōu)化技巧

    Android幀率監(jiān)測與優(yōu)化技巧

    Android 應用的性能優(yōu)化是開發(fā)過程中至關重要的一環(huán),而幀率(Frame Rate)是評估應用性能的一個關鍵指標,在本文中,我們將深入探討如何監(jiān)測 Android 應用的幀率,以及如何通過代碼示例來優(yōu)化應用的性能,需要的朋友可以參考下
    2023-10-10

最新評論