首页 > 解决方案 > flutter_downloader 获得许多任务的进度

问题描述

我正在使用 Flutter_downloader 包开发下载管理器应用程序,它是唯一为我们提供了很多选项的包,例如暂停、恢复、重试、取消、删除等等,但我面临的问题是进度问题。

我正在使用下载模型文件来定义下载

import 'package:flutter/material.dart';

class Download {
  final String name;
  final String size;
  final String status;
  final String timeLeft;
  final String transferRate;
  final String type;
  final String path;
  final String icon;
  int progress;

  Download({
    @required this.name,
    @required this.size,
    @required this.status,
    @required this.timeLeft,
    @required this.transferRate,
    @required this.type,
    @required this.path,
    @required this.icon,
    @required this.progress,
  });
}

并下载提供程序文件以获取所有下载并处理所有下载操作

import 'dart:isolate';
import 'dart:ui';

import 'package:idminternetdownloadmanager/models/download.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:http/http.dart' as http;
import 'package:ext_storage/ext_storage.dart';

class DownloadsProvider with ChangeNotifier {
  List<Download> _downloads = [];

  List<Download> get downloads {
    return [..._downloads];
  }

  void addDownload(String url) async {
    var taskId;
    //set name
    final name = url.split('/').last;
    //set type
    final type = url.split('.').last;
    //set icon
    final icon = type == 'pdf'
        ? 'lib/assets/pdf.png'
        : type == 'txt'
            ? 'lib/assets/txt.png'
            : type == 'docx' || type == 'doc'
                ? 'lib/assets/doc.png'
                : type == 'zip' || type == 'rar'
                    ? 'lib/assets/rar.png'
                    : type == 'iso'
                        ? 'lib/assets/iso.png'
                        : type == 'tif' ||
                                type == 'jpg' ||
                                type == 'gif' ||
                                type == 'png' ||
                                type == 'raw'
                            ? 'lib/assets/png.png'
                            : type == 'flv' ||
                                    type == 'avi' ||
                                    type == 'mov' ||
                                    type == 'mpeg' ||
                                    type == 'mp4' ||
                                    type == 'ogg' ||
                                    type == 'wmv' ||
                                    type == 'webm' ||
                                    type == '3gp'
                                ? 'lib/assets/mp4.png'
                                : type == 'mp3' ||
                                        type == 'wma' ||
                                        type == 'mid' ||
                                        type == 'wav'
                                    ? 'lib/assets/mp3.png'
                                    : type == 'java'
                                        ? 'lib/assets/java.png'
                                        : type == 'rss'
                                            ? 'lib/assets/rss.png'
                                            : type == 'php'
                                                ? 'lib/assets/php.png'
                                                : type == 'xml'
                                                    ? 'lib/assets/xml.png'
                                                    : type == 'html'
                                                        ? 'lib/assets/html.png'
                                                        : type == 'css'
                                                            ? 'lib/assets/css.png'
                                                            : 'lib/assets/unknown.png';
    //set size
    String size;
    http.Response r = await http.head(url);
    final fileSize = int.parse(r.headers["content-length"]);
    if (fileSize >= 1024 && fileSize < 1048576) {
      size = '${(fileSize / 1024).toStringAsFixed(2)} KB';
    } else if (fileSize >= 1048576 && fileSize < 1073741824) {
      size = '${(fileSize / 1048576).toStringAsFixed(2)} MB';
    } else {
      size = '${(fileSize / 1073741824).toStringAsFixed(2)} G';
    }
    //set downloads directory path
    String path = await ExtStorage.getExternalStoragePublicDirectory(
        ExtStorage.DIRECTORY_DOWNLOADS);
    //start download
    final storagePermission = await Permission.storage.request();
    if (storagePermission.isGranted) {
      taskId = await FlutterDownloader.enqueue(
        url: url,
        savedDir: path,
        showNotification:
            true, // show download progress in status bar (for Android)
        openFileFromNotification:
            true, // click on notification to open downloaded file (for Android)
      );
    } else {
      return;
    }
    
    
    // trying a different way to get progress
    try {
      final tasks = await FlutterDownloader.loadTasksWithRawQuery(
          query: 'SELECT * FROM task WHERE status=3 AND progress<>0');
      final task = tasks.firstWhere((task) => task.taskId == taskId);
      int progress = task.progress;
      print(progress);
    } catch (e) {
      print(e);
    } // and it doesn't work
    
    
    _downloads.add(Download(
      name: name,
      size: size,
      status: 'Unknown',
      timeLeft: 'Unknown',
      transferRate: 'Unknown',
      type: type,
      path: path,
      icon: icon,
      progress: 5555,
    ));
    notifyListeners();
  }
}

这是我正在构建的照片 // StackOverFlow 不希望我上传照片

这是我的用户界面

@override
  Widget build(BuildContext context) {
    final downloadList = Provider.of<DownloadsProvider>(context).downloads;
    return GestureDetector(
      onTapDown: storePosition,
      onLongPress: () {
        setState(() {
          rowColor = Colors.blue;
        });
        showPopupMenu();
      },
      //showPopupMenu,
      child: Container(
        //height: 25,
        decoration: BoxDecoration(
          color: rowColor,
          border: Border(
            bottom: BorderSide(width: 1, color: Colors.grey[350]),
          ),
        ),
        child: Row(
          children: <Widget>[
            NameRowContainer(
              data: downloadList[widget.index].name,
              icon: downloadList[widget.index].icon,
            ),
            RowContainer(
                data: downloadList[widget.index].size,
                lastOne: false,
                width: 100),
            RowContainer(
              // I want to show progress here
                data: downloadList[widget.index].status,
                lastOne: false,
                width: 100),
            RowContainer(
                data: downloadList[widget.index].timeLeft,
                lastOne: false,
                width: 85),
            RowContainer(
                data: downloadList[widget.index].transferRate,
                lastOne: true,
                width: 120),
          ],
        ),
      ),
    );
  }

所以问题是我无法获得每个任务的进度并将其存储为下载模型中的进度变量,然后我可以在数据表中将其显示给用户,如上图所示,然后基于它创建一个线性进度指示器软件包提供的获得进度的方式它适用于单个文件而不适用于所有文件,或者至少我无法解决任何想法?

标签: flutter

解决方案


使用此回调:

static void downloadCallback(
      String id, DownloadTaskStatus status, int progress) {
    final SendPort send =
        IsolateNameServer.lookupPortByName('MyAppPrgrss' + id);
    send.send([id, status, progress]);
  }

这在你的 UI 部分:

void _bindBackgroundIsolate() {
    bool isSuccess = IsolateNameServer.registerPortWithName(
        _port.sendPort, port + _downloadTaskId);
    if (!isSuccess) {
      _unbindBackgroundIsolate();
      _bindBackgroundIsolate();
      return;
    }
    _port.listen((dynamic data) {
      String id = data[0];
      DownloadTaskStatus status = data[1];
      int progress = data[2];

      setState(() {
        if (id == _downloadTaskId) {
          this.progress = progress;

          if (status == DownloadTaskStatus.complete) {
            // TODO
          }
        }
      });
    });
  }

  void _unbindBackgroundIsolate() {
    IsolateNameServer.removePortNameMapping('MyAppPrgrss$_downloadTaskId');
  }

开始下载后注册回调并初始化taskID

   String _downloadTaskId = await FlutterDownloader.enqueue(
    url: downloadUrl,
    savedDir: path,
    fileName: fileName,
    showNotification: true,
    openFileFromNotification: true,
  );

FlutterDownloader.registerCallback(downloadCallback);

推荐阅读