【问题标题】:flutter - How to download asset when apps launched and used itflutter - 如何在应用程序启动和使用时下载资产
【发布时间】:2019-10-31 23:54:14
【问题描述】:

目前,我的应用程序有许多资产(图像、声音、字体、json、SQL-lite 数据库文件等)。都在pubspec.yaml中定义了

但是,由于要求减小 APK 大小,我需要在应用启动时下载其中的一些并将其保存到存储中,因此下次无需下载。 p>

如果资产还没有准备好,它应该等待一秒钟并显示加载栏圈。

问题是如何做这件事,有什么例子吗?

【问题讨论】:

    标签: android flutter google-play-services hybrid-mobile-app


    【解决方案1】:

    最简单的方法是将文件下载为 zip(存档文件)并解压到应用程序存储目录的路径getApplicationDocumentsDirectory

    您将使用以下软件包列表: archive , httppath_provider

    pubspec.yaml 看起来像

    version: 1.0.0+1
    
    environment:
      sdk: ">=2.1.0 <3.0.0"
    
    dependencies:
      flutter:
        sdk: flutter
    
      path_provider: ^1.1.0
      http: ^0.12.0+2
      archive: ^2.0.8
    
    dev_dependencies:
      flutter_test:
        sdk: flutter
      uses-material-design: true
      assets:
        - assets/images/
    

    加冕您的应用程序看起来像的 main.dart 文件 请注意,api 是您的文件的 URL,没有文件名。

    main.dart

    import 'dart:io';
    
    import 'package:archive/archive.dart';
    import 'package:flutter/material.dart';
    import 'package:http/http.dart' as http;
    import 'package:path_provider/path_provider.dart';
    
    import 'data.dart';
    
    const api =
        'https://firebasestorage.googleapis.com/v0/b/playground-a753d.appspot.com/o';
    
    enum AppTheme { candy, cocktail }
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(AppTheme.candy),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      final AppTheme theme;
    
      MyHomePage(this.theme);
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      AppTheme _theme;
      String _dir;
      List<String> _images;
    
      @override
      void initState() {
        super.initState();
        _theme = widget.theme;
        _images = data[_theme];
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          floatingActionButton: FloatingActionButton(
            child: Icon(Icons.style),
            onPressed: () async {
              if (_theme == AppTheme.candy) {
                await _downloadAssets('cocktail');
              }
              setState(() {
                _theme =
                    _theme == AppTheme.candy ? AppTheme.cocktail : AppTheme.candy;
                _images = data[_theme];
              });
            },
          ),
          body: ListView.builder(
              itemCount: _images.length,
              itemBuilder: (BuildContext context, int index) {
                return _getImage(_images[index], _dir);
              }),
        );
      }
    
      Widget _getImage(String name, String dir) {
        if (_theme != AppTheme.candy) {
          var file = _getLocalImageFile(name, dir);
          return Image.file(file);
        }
        return Image.asset('assets/images/$name');
      }
    
      File _getLocalImageFile(String name, String dir) => File('$dir/$name');
    
      Future<void> _downloadAssets(String name) async {
        if (_dir == null) {
          _dir = (await getApplicationDocumentsDirectory()).path;
        }
    
        if (!await _hasToDownloadAssets(name, _dir)) {
          return;
        }
        var zippedFile = await _downloadFile(
            '$api/$name.zip?alt=media&token=7442d067-a656-492f-9791-63e8fc082379',
            '$name.zip',
            _dir);
    
        var bytes = zippedFile.readAsBytesSync();
        var archive = ZipDecoder().decodeBytes(bytes);
    
        for (var file in archive) {
          var filename = '$_dir/${file.name}';
          if (file.isFile) {
            var outFile = File(filename);
            outFile = await outFile.create(recursive: true);
            await outFile.writeAsBytes(file.content);
          }
        }
      }
    
      Future<bool> _hasToDownloadAssets(String name, String dir) async {
        var file = File('$dir/$name.zip');
        return !(await file.exists());
      }
    
      Future<File> _downloadFile(String url, String filename, String dir) async {
        var req = await http.Client().get(Uri.parse(url));
        var file = File('$dir/$filename');
        return file.writeAsBytes(req.bodyBytes);
      }
    }
    

    然后你必须列出所有文件并添加它们(逻辑上到相应的主题)

    data.dart:

    import 'main.dart' show AppTheme;
    
    const Map<AppTheme, List<String>> data = const {
      AppTheme.candy: [
        'art-background-blue-1289363.jpg',
        'assortment-bright-candy-1043519.jpg',
        'bright-candies-cherry-1405760.jpg',
        'bright-candies-colorful-539447.jpg',
        'bright-candy-chewy-1328885.jpg',
      ],
      AppTheme.cocktail: [
        'alcohol-alcoholic-beverage-beverage-1304540.jpg',
        'alcohol-alcoholic-beverage-beverage-1723638.jpg',
        'alcohol-black-background-close-up-800390.jpg',
        'alcoholic-beverage-beverage-cocktail-970197.jpg',
        'bar-beverage-blur-338713.jpg',
      ]
    };
    

    更多信息请查看Github projectMedium article

    【讨论】:

    • 欢迎,如果它对你有用,请接受答案:)
    • 嗨,我仍然对这段代码感到困惑:for (var file in archive) { var filename = '$_dir/${file.name}'; if (file.isFile) { var outFile = File(filename); outFile = await outFile.create(recursive: true); await outFile.writeAsBytes(file.content); } } 为什么我们需要它。如果 zip 文件包含根文件夹怎么办?
    • 再次欢迎,此代码支持直接包含文件列表的 zip 文件。如果你要去和文件夹它会更复杂。您可以查看存档包 pub.dev/packages/archive#-example-tab- 中的示例。如果你弄明白了,它会尝试为你编写代码。
    • 我想我会使用不包含根文件夹的 zip 文件。但是,要验证我的应用程序必须下载 zip 并解压缩,我需要知道资产文件的位置。我将使用文件管理器应用程序在 Android 上浏览它。有什么想法吗?
    • 您可以通过普通文件资源管理器查看应用程序文件。如果您想自己检查文件而不是代码,首先您必须打印包含(await getApplicationDocumentsDirectory()).path_dir var。然后使用 android studio device file explorer 到达该路径,您将在右下角找到。请注意,您的应用必须处于调试模式。
    猜你喜欢
    • 2018-09-20
    • 2021-03-28
    • 2018-10-11
    • 2016-05-24
    • 2018-05-11
    • 2019-01-24
    • 2021-11-07
    • 2019-04-06
    相关资源
    最近更新 更多