【问题标题】:Flutter pre-cache imagesFlutter 预缓存图像
【发布时间】:2020-10-14 22:11:02
【问题描述】:

我正在开发一个 Flutter 项目,我想在应用启动时预缓存图像。 这个想法是当你第一次启动应用程序时,它会下载一个图像列表,或者缓存/存储在数据库中/存储在本地存储中/或任何其他可行的解决方案。我真的不知道这里的最佳做法。然后当您下次启动应用程序时,您已经拥有照片,因此您不想再次下载它们(基于后端数据的版本)。 就我所见;

  • 缓存,我真的不知道它是否不够持久,我不知道我是否有足够的控制权。
  • 本地存储,我想我得请求用户权限才能访问设备的文件
  • 数据库,每次我想保存/获取照片时,我都必须对照片进行编码/解码,因此需要进行一些计算。

我的理想选择是数据库,因为我可以控制数据,而且它是一个相当小的应用程序,因此计算量很小,我不必征求用户许可。

在过去的几天里,我尝试使用上述所有解决方案来实现这一点,但我无法让它发挥作用。

现在我想将Image 存储到数据库中(我正在使用sqflite)而不显示它,然后读取它以从另一个屏幕将其显示为Widget。我有 2 个屏幕,第一个屏幕调用 SplashScreen 来获取和保存图像,第二个屏幕调用 HomeScreen 从数据库中读取图像并显示它们。

SplashScreen.dart:

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>[],
        ),
      )
    );
  }
}

我可以重新考虑遵循最佳做法的任何一点。

非常感谢您的帮助。

【问题讨论】:

  • 您找到解决方案了吗?

标签: android flutter sqflite flutter-image


【解决方案1】:

你可以使用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()
     ),

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-10-23
    • 2019-10-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-17
    • 1970-01-01
    • 2020-06-01
    • 2018-11-29
    相关资源
    最近更新 更多