Flutter预缓存图片

4
我正在开发一个Flutter项目,在应用启动时我想要预缓存图片。我的想法是,当您第一次启动应用程序时,会下载一系列图像,然后将它们缓存/存储在数据库中/存储在本地存储中/或使用其他可行的解决方案。我不知道最佳实践是什么。然后,当您下次启动应用程序时,已经有了照片,因此您不需要再次下载它们(基于后端数据的版本)。根据我所看到的:
  • 缓存,我不确定是否持久化,而且我不知道我能否对其进行充分的控制。
  • 本地存储,我认为我必须请求用户权限来访问设备上的文件。
  • 数据库,每次保存/获取图像时都必须对其进行编码/解码,因此这将需要一些计算。
我理想的选择是数据库,因为我可以控制数据,并且这是一个非常小的应用程序,所以计算量很小,我不需要请求用户权限。
我在过去几天里尝试使用上述每种解决方案来实现此目标,但没有成功。
现在,我想将Image存储到数据库中(我正在使用sqflite),并在另一个屏幕中将其作为Widget读取以显示它。我有两个屏幕,第一个称为SplashScreen以获取和保存图像,第二个是HomeScreen以从数据库中读取图像并显示它们。 :
class SplashScreen extends StatefulWidget {
  @override
  _SplashScreenState createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> with SingleTickerProviderStateMixin {
  bool hasInternet = true;
  var subscription;
  double loading = 0;

  @override
  initState() {
    super.initState();
    getPhotos();
    subscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult connectivityResult) {
      setState(() {
        hasInternet = connectivityResult == ConnectivityResult.mobile || connectivityResult == ConnectivityResult.wifi;
      });
    });
  }
  dispose() {
    super.dispose();
    subscription.cancel();
  }

  Future getPhotos() async {
    List<String> photoUrls = await fetchPhotos();
    photoUrls.asMap().forEach((index, photoUrl) async {
      var response = await http
        .get(photoUrl);
      loading = index / photoUrls.length;
      // Convert Photo response and save them in DB
      imageDBFormat = ...
      savePhotosInDB(imageDBFormat)
    });
  }

 

  @override
  Widget build(BuildContext context) {
    if(loading == 1) {
      Navigator.pushNamed(context, '/');
    }

    return Center(
      child: Container(
        decoration: BoxDecoration(
          image: DecorationImage(
            image: AssetImage("assets/back.png"), 
            fit: BoxFit.cover,
          )
        ),
        child: Scaffold(
          backgroundColor: Theme.of(context).backgroundColor,
          body: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  Container(
                    width: 300,
                    child: LinearProgressIndicator(
                      value: loading,
                      valueColor: AlwaysStoppedAnimation<Color>(ProjectColors.primaryDark),
                    ),
                  )
                ],
              ),
            ],
          )
        ),
      ),
    );
  }
}

HomeScreen.dart:

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateMixin {
  List<Widget> images;

  initState() {
    super.initState();
    getImages();
  }

  void getImages() async {
    List imgs = getImagesFromDB();

    setState(() {
      images = imgs.map((image) {
        // Convert imgs from db into Widget
        Widget imageWidget = ...
        return Container(
          child: imageWidget,
        );
      }).toList();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        image: DecorationImage(
          image: AssetImage("assets/back.png"), 
          fit: BoxFit.cover,
        )
      ),
      child: Scaffold(
        backgroundColor: Theme.of(context).backgroundColor,
        body: Column(
          children: images == null ? images : <Widget>[],
        ),
      )
    );
  }
}

我很乐意重新考虑任何观点以遵循最佳实践。

非常感谢您的帮助。


1
你找到解决方案了吗? - Gareth Beall
1个回答

0
你可以使用https://pub.dev/packages/cached_network_image库,它已经使用sqlite作为存储,并且你可以配置持久化的时间。
class CustomCacheManager extends BaseCacheManager {
  static const key = "customCache";

  static CustomCacheManager _instance;

  factory CustomCacheManager() {
    if (_instance == null) {
      _instance = new CustomCacheManager._();
    }
    return _instance;
  }

  CustomCacheManager._() : super(key,
      maxAgeCacheObject: Duration(months: 6),
      maxNrOfCacheObjects: 100);

  Future<String> getFilePath() async {
    var directory = await getTemporaryDirectory();
    return p.join(directory.path, key);
  }
}

然后你可以在你的构建方法中使用:

CachedNetworkImage(
        imageUrl: "http://via.placeholder.com/350x150",
        placeholder: (context, url) => CircularProgressIndicator(),
        errorWidget: (context, url, error) => Icon(Icons.error),
        cacheManager: CustomCacheManager()
     ),

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接