検索
[Flutter/Dart]画像取得待ちの間は異なる表示方法とする
- M.R 
- 2023年7月16日
- 読了時間: 2分
やりたいこと
- 画像を表示するWidgetがある 
- 画像はリモートのストレージから取得する 
- 取得するまでは時間がかかるので、その間は待機中である旨を伝える表示としたい。 よくあるのはぐるぐる 
解決策
FutureBuildrで表示を切り替えましょう。
FutureBuilder<ImageProvider>(
  future: getImage(),  
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return CircularProgressIndicator();
    }
    if ((snapshot.hasError) || (!snapshot.hasData)){
      //Error handling
    }
    return Container(
      width: 100,
      height: 100,
      decoration: BoxDecoration(
        borderRadius: const 
        BorderRadius.all(Radius.circular(10)),
        image: DecorationImage(
          fit: BoxFit.contain,
          image: snapshot.data!
        ),
      )
    );
  }
)Future<ImageProvider> getImage()async{
  //method to get image from remote storage
}異なる画像ソースで処理を共通化
上記では画像のソースとしてリモートストレージを考えたが、ローカルファイルの場合もあるし、assetにある画像ファイルの場合もある。これらの異なるソースに対して処理を共通化するにはどうしたらいいでしょうか。
以下のようなポリモーフィックなクラスを作りましょう。
- 抽象クラスImageSourceクラスを作る 
- ImageSourceクラスにFuture<ImageProvider> getImage()を定義 
- ImageSourceクラスを継承した具象クラスLocalImage、RemoteImageを定義し、getImageの実装を各々追加 
- 画像表示Widgetは、ImageSourceのインスタンスを引数にとり、getImage()を呼んでImageProviderを取得 
abstract class ImageSource{
  String path;  //画像パス 
  Future<ImageProvider> getImage();  //画像取得
}
//ローカルストレージのファイル
class LocalImage extends ImageSource{
  @override
  Future<ImageProvider> getImage()async{
    return FileImage(File(path));
  }
}
//リモートストレージのファイル
class RemoteImage extends ImageSource{
  @override
  Future<ImageProvider> getImage()async{
    String _downloadPath = await _downLoadFile();  //ファイルダウンロード処理
    return NetworkImage(_downloadPath);
  }
}
Widget ImageWidget(ImageSource imgSrc){
  return FutureBuilder<ImageProvider>(
    future: imgSrc.getImage(),  
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.waiting) {
        return CircularProgressIndicator();
      }
      if ((snapshot.hasError) || (!snapshot.hasData)){
        //Error handling
      }
      return Container(
        width: 100,
        height: 100,
        decoration: BoxDecoration(
          borderRadius: const 
          BorderRadius.all(Radius.circular(10)),
          image: DecorationImage(
            fit: BoxFit.contain,
            image: snapshot.data!
          ),
        )
      );
    }
  )
}LocalImageの場合、getImage()をasyncにする必要はないですが、RemoteImageと都合を合わせるためにasyncにしています。
(ぐるぐるがほとんど表示されずに画像が表示されるだけです)






コメント