3

我正在开发一个 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>[],
        ),
      )
    );
  }
}

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

非常感谢你的帮助。

4

1 回答 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()
     ),
于 2020-06-25T11:53:30.963 回答