Flutter文件下载管理插件al_downloader的使用

发布于 1周前 作者 phonegap100 来自 Flutter

Flutter文件下载管理插件al_downloader的使用

1. 简介

al_downloader 是一个基于URL的Flutter下载管理器,支持下载任意类型的文件,并自动管理许多与下载相关的事情。它基于 flutter_downloader 插件,提供了更简洁的API和更多的功能。

2. 功能特性

  • 按URL管理下载任务:通过URL来管理下载任务。
  • 简单的下载状态:提供清晰的下载状态(未开始、下载中、暂停、失败、成功)。
  • 减少I/O操作:优化了I/O操作,减少了不必要的磁盘读写。
  • 方便的下载处理接口:提供了便捷的下载事件处理接口。
  • 支持批量下载:可以同时下载多个文件。
  • 自动管理文件路径:无需指定下载路径,插件会自动管理文件存储。
  • 基于 flutter_downloader:继承了 flutter_downloader 的强大功能。

3. 集成步骤

3.1 添加依赖

pubspec.yaml 文件中添加以下依赖:

dependencies:
  al_downloader: ^1.8.4

然后运行以下命令来获取依赖:

flutter packages get
3.2 导入库

在需要使用 al_downloader 的Dart文件中导入以下代码:

import 'package:al_downloader/al_downloader.dart';

4. 使用示例

4.1 初始化

在应用启动时调用 ALDownloader.initialize() 来初始化下载管理器:

void initialize() {
  ALDownloader.initialize();
  
  // 配置日志输出,可以选择是否频繁打印日志
  ALDownloader.configurePrint(true, frequentEnabled: false);
}
4.2 单个文件下载

可以通过 ALDownloader.download() 方法下载单个文件,并监听下载进度和其他事件:

ALDownloader.download(url,
    directoryPath: directoryPath, // 可选参数,指定下载目录
    fileName: fileName, // 可选参数,指定文件名
    handlerInterface: ALDownloaderHandlerInterface(
      progressHandler: (progress) {
        debugPrint('下载进度 = $progress, URL = $url');
      },
      succeededHandler: () {
        debugPrint('下载成功, URL = $url');
      },
      failedHandler: () {
        debugPrint('下载失败, URL = $url');
      },
      pausedHandler: () {
        debugPrint('下载暂停, URL = $url');
      },
    ));
4.3 批量下载

可以通过 ALDownloaderBatcher.download() 方法进行批量下载:

ALDownloaderBatcher.download(urls,
    handlerInterface: ALDownloaderHandlerInterface(
      progressHandler: (progress) {
        debugPrint('批量下载进度 = $progress');
      },
      succeededHandler: () {
        debugPrint('批量下载成功');
      },
      failedHandler: () {
        debugPrint('批量下载失败');
      },
      pausedHandler: () {
        debugPrint('批量下载暂停');
      },
    ));
4.4 暂停、取消和移除下载任务
  • 暂停下载ALDownloader.pause(url),暂停下载但保留已下载的部分。
  • 取消下载ALDownloader.cancel(url),取消下载并删除已下载的部分。
  • 移除下载任务ALDownloader.remove(url),移除下载任务并删除所有相关数据。
4.5 获取下载状态和进度
  • 获取下载状态await ALDownloader.getStatusForUrl(url),返回当前下载任务的状态。
  • 获取下载进度await ALDownloader.getProgressForUrl(url),返回当前下载任务的进度。
4.6 获取下载任务
  • 获取单个任务await ALDownloader.getTaskForUrl(url),返回指定URL的下载任务信息。
  • 获取所有任务await ALDownloader.tasks,返回所有下载任务的列表。

5. 完整示例Demo

以下是一个完整的示例应用程序,展示了如何使用 al_downloader 进行批量下载、暂停、取消和移除下载任务。

import 'package:flutter/material.dart';
import 'package:al_downloader/al_downloader.dart';

void main() {
  runApp(const MyApp());
}

/* ----------------------------------------------UI---------------------------------------------- */

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    const title = 'al_downloader';
    return MaterialApp(
      title: title,
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const MyHomePage(title: title),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  [@override](/user/override)
  void initState() {
    super.initState();
    initialize();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: Stack(fit: StackFit.expand, children: [
        Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            const SizedBox(height: 10),
            const Text('您正在测试批量下载',
                textAlign: TextAlign.center,
                style: TextStyle(
                    fontSize: 25,
                    fontWeight: FontWeight.bold,
                    color: Colors.black)),
            Expanded(child: theListview)
          ],
        ),
        Positioned(
          left: 0,
          right: 0,
          bottom: MediaQuery.of(context).padding.bottom + 10,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            mainAxisSize: MainAxisSize.min,
            children: theActionLists
                .map((e) => Expanded(
                      child: Padding(
                        padding: const EdgeInsets.fromLTRB(3, 0, 3, 0),
                        child: MaterialButton(
                          padding: const EdgeInsets.all(0),
                          minWidth: 20,
                          height: 50,
                          color: Colors.blue,
                          textTheme: ButtonTextTheme.primary,
                          onPressed: e[1],
                          child: Text(
                            e[0],
                            style: const TextStyle(fontSize: 10),
                          ),
                        ),
                      ),
                    ))
                .toList(),
          ),
        ),
      ]),
    );
  }

  /// 核心数据在ListView中展示
  get theListview => ListView.separated(
        padding: EdgeInsets.only(
            top: 20, bottom: MediaQuery.of(context).padding.bottom + 75),
        shrinkWrap: true,
        itemCount: models.length,
        itemBuilder: (BuildContext context, int index) {
          final model = models[index];
          final order = index + 1;
          return Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Align(
                alignment: Alignment.centerLeft,
                child: Text(
                  '$order',
                  style: const TextStyle(
                      fontSize: 20,
                      color: Colors.black,
                      fontWeight: FontWeight.bold),
                ),
              ),
              Align(
                alignment: Alignment.centerLeft,
                child: Text(
                  model.url,
                  style: const TextStyle(fontSize: 11, color: Colors.black),
                ),
              ),
              SizedBox(
                height: 30,
                child: Stack(fit: StackFit.expand, children: [
                  LinearProgressIndicator(
                    value: model.progress,
                    backgroundColor: Colors.grey,
                    valueColor: const AlwaysStoppedAnimation<Color>(Colors.blue),
                  ),
                  Align(
                    alignment: Alignment.centerLeft,
                    child: Text(
                      '进度 = ${model.progressForPercent}',
                      style: const TextStyle(fontSize: 13, color: Colors.white),
                    ),
                  ),
                  Align(
                    alignment: Alignment.centerRight,
                    child: Text(
                      model.status.alDescription,
                      style: const TextStyle(fontSize: 13, color: Colors.white),
                    ),
                  )
                ]),
              )
            ],
          );
        },
        separatorBuilder: (BuildContext context, int index) =>
            const Divider(height: 10, color: Colors.transparent),
      );

  /// 操作按钮列表
  late final theActionLists = <List>[
    ['下载', _batchDownloadAction],
    ['暂停', _pauseAllAction],
    ['取消', _cancelAllAction],
    ['移除', _removeAllAction]
  ];

  /* ----------------------------------------------Action---------------------------------------------- */

  void _batchDownloadAction() {
    batchDownload();
  }

  void _pauseAllAction() {
    ALDownloader.pauseAll();
  }

  void _cancelAllAction() {
    ALDownloader.cancelAll();
  }

  void _removeAllAction() {
    ALDownloader.removeAll();
  }

  /* ----------------------------------------------ALDownloader---------------------------------------------- */

  /// 初始化
  void initialize() {
    /// ALDownloader 初始化
    ALDownloader.initialize();

    /// 配置日志输出
    ALDownloader.configurePrint(false, frequentEnabled: false);

    // 添加永久的下载处理接口
    addForeverHandlerInterface();

    // 添加批量下载的一次性处理接口
    addHandlerInterfaceForBatch();
  }

  /// 批量下载
  void batchDownload() {
    final urls = models.map((e) => e.url).toList();
    final id = ALDownloaderBatcher.download(urls,
        handlerInterface: ALDownloaderHandlerInterface(
          progressHandler: (progress) {
            debugPrint('批量下载进度 = $progress');
          },
          succeededHandler: () {
            debugPrint('批量下载成功');
          },
          failedHandler: () {
            debugPrint('批量下载失败');
          },
          pausedHandler: () {
            debugPrint('批量下载暂停');
          },
        ));

    if (id != null) _handlerInterfaceIdsForBatch.add(id);
  }

  /// 添加永久的下载处理接口
  void addForeverHandlerInterface() {
    for (final model in models) {
      final url = model.url;
      final id = ALDownloader.addForeverHandlerInterface(
          ALDownloaderHandlerInterface(
            progressHandler: (progress) {
              debugPrint('下载进度 = $progress, URL = $url');

              model.status = ALDownloaderStatus.downloading;
              model.progress = progress;

              setState(() {});
            },
            succeededHandler: () {
              debugPrint('下载成功, URL = $url');

              model.status = ALDownloaderStatus.succeeded;

              setState(() {});
            },
            failedHandler: () async {
              debugPrint('下载失败, URL = $url');

              final status = await ALDownloader.getStatusForUrl(url);
              model.status = status;

              setState(() {});
            },
            pausedHandler: () {
              debugPrint('下载暂停, URL = $url');

              model.status = ALDownloaderStatus.paused;

              setState(() {});
            },
          ),
          url);

      _handlerInterfaceIds.add(id);
    }
  }

  /// 添加批量下载的一次性处理接口
  void addHandlerInterfaceForBatch() {
    final urls = models.map((e) => e.url).toList();
    final id = ALDownloaderBatcher.addHandlerInterface(
        ALDownloaderHandlerInterface(
          progressHandler: (progress) {
            debugPrint('批量下载进度 = $progress');
          },
          succeededHandler: () {
            debugPrint('批量下载成功');
          },
          failedHandler: () {
            debugPrint('批量下载失败');
          },
          pausedHandler: () {
            debugPrint('批量下载暂停');
          },
        ),
        urls);

    _handlerInterfaceIdsForBatch.add(id);
  }

  /// 移除批量下载的处理接口
  void removeHandlerInterfaceForBatch() {
    for (final element in _handlerInterfaceIdsForBatch) {
      ALDownloaderBatcher.removeHandlerInterfaceForId(element);
    }

    _handlerInterfaceIdsForBatch.clear();
  }

  /// 管理 [ALDownloaderHandlerInterface] 通过 [ALDownloaderHandlerInterfaceId]
  final _handlerInterfaceIds = <ALDownloaderHandlerInterfaceId>[];

  /// 管理批量 [ALDownloaderHandlerInterface] 通过 [ALDownloaderHandlerInterfaceId]
  final _handlerInterfaceIdsForBatch = <ALDownloaderHandlerInterfaceId>[];
}

/* ----------------------------------------------Model class---------------------------------------------- */

class DownloadModel {
  final String url;

  double progress = 0;

  String get progressForPercent {
    int aProgress = (progress * 100).toInt();
    return '$aProgress%';
  }

  ALDownloaderStatus status = ALDownloaderStatus.unstarted;

  DownloadModel(this.url);
}

extension _ALDownloaderStatusExtension on ALDownloaderStatus {
  String get alDescription =>
      ['未开始', '下载中', '暂停', '失败', '成功'][index];
}

/* ----------------------------------------------Data---------------------------------------------- */

final models = kTestVideos.map((e) => DownloadModel(e)).toList();

final kTestVideos = [
  'https://media.w3.org/2010/05/sintel/trailer.mp4',
  'http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4',
  'http://vjs.zencdn.net/v/oceans.mp4',
  'http://mirror.aarnet.edu.au/pub/TED-talks/911Mothers_2010W-480p.mp4',
  'http://downsc.chinaz.net/Files/DownLoad/sound1/201906/11582.mp3'
];

更多关于Flutter文件下载管理插件al_downloader的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter文件下载管理插件al_downloader的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,al_downloader 是一个强大的文件下载管理插件,它提供了丰富的功能来管理文件下载任务。以下是如何在Flutter项目中使用 al_downloader 插件的一个基本示例,包括初始化、创建下载任务以及监听下载进度的代码。

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 al_downloader 依赖:

dependencies:
  flutter:
    sdk: flutter
  al_downloader: ^最新版本号  # 请替换为实际最新版本号

然后运行 flutter pub get 来获取依赖。

2. 初始化插件

在你的 Flutter 应用中,通常会在 main.dart 或一个专门负责下载管理的 Dart 文件中初始化 al_downloader

import 'package:flutter/material.dart';
import 'package:al_downloader/al_downloader.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 初始化下载管理器
    AlDownloader.init();
    return MaterialApp(
      home: DownloadScreen(),
    );
  }
}

3. 创建下载任务

接下来,你可以创建一个下载任务的函数。例如,在一个按钮点击事件中启动下载。

class DownloadScreen extends StatefulWidget {
  @override
  _DownloadScreenState createState() => _DownloadScreenState();
}

class _DownloadScreenState extends State<DownloadScreen> {
  final _url = 'https://example.com/file.zip'; // 替换为实际的下载URL
  final _savePath = '/storage/emulated/0/Download/file.zip'; // 替换为实际的保存路径

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('File Downloader'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            await downloadFile();
          },
          child: Text('Start Download'),
        ),
      ),
    );
  }

  Future<void> downloadFile() async {
    try {
      // 创建下载任务
      final taskId = await AlDownloader.createDownloadTask(
        url: _url,
        savePath: _savePath,
        fileName: 'file.zip', // 可选,指定文件名
        headers: { // 可选,添加HTTP头
          'Authorization': 'Bearer YOUR_TOKEN',
        },
      );

      // 监听下载进度
      AlDownloader.listenProgress(taskId, (progress) {
        print('Download Progress: ${progress.progress}%');
        if (progress.status == DownloadTaskStatus.completed) {
          print('Download Completed!');
        }
      });
    } catch (e) {
      print('Download Error: $e');
    }
  }
}

4. 处理下载任务的其他操作

你还可以处理其他操作,如暂停、恢复和取消下载任务。

// 暂停下载任务
AlDownloader.pauseDownload(taskId);

// 恢复下载任务
AlDownloader.resumeDownload(taskId);

// 取消下载任务
AlDownloader.cancelDownload(taskId);

5. 清理资源

当你的应用不再需要时,可以调用以下方法来清理资源:

@override
void dispose() {
  AlDownloader.dispose();
  super.dispose();
}

请注意,以上代码是一个基本的示例,实际应用中你可能需要处理更多的边界情况和错误处理。另外,由于 Android 和 iOS 对于文件存储和权限管理的不同,你可能还需要根据平台进行相应的配置和权限请求。

希望这个示例能帮助你更好地理解和使用 al_downloader 插件进行文件下载管理。

回到顶部