Flutter文件下载管理插件simple_downloader的使用
Flutter文件下载管理插件simple_downloader的使用
simple_downloader
是一个用于在Flutter项目中处理HTTP文件下载的简单且易于使用的插件。
安装
在你的Flutter项目的pubspec.yaml
文件中添加依赖:
dependencies:
...
simple_downloader: ^0.0.3
然后运行flutter pub get
来获取新的依赖项。
导入包
在你的Dart文件中导入simple_downloader
包:
import 'package:simple_downloader/simple_downloader.dart';
初始化
首先,你需要初始化SimpleDownloader
对象,并设置一些基本参数。以下是一个完整的示例代码:
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:path_provider/path_provider.dart' as path;
import 'package:simple_downloader/simple_downloader.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late SimpleDownloader _downloader;
double _progress = 0.0;
int _offset = 0;
int _total = 0;
DownloadStatus _status = DownloadStatus.undefined;
DownloaderTask _task = const DownloaderTask(
url:
"https://images.unsplash.com/photo-1615220368123-9bb8faf4221b?ixlib=rb-1.2.1&dl=vadim-kaipov-f6jkAE1ZWuY-unsplash.jpg&q=80&fm=jpg&crop=entropy&cs=tinysrgb",
fileName: "images_downloaded.jpg",
bufferSize:
1024, // 如果未设置bufferSize,默认值为64(64Kb)
);
@override
void initState() {
super.initState();
init();
}
@override
void dispose() {
_downloader.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('文件下载管理示例'),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
height: 150,
width: double.maxFinite,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
boxShadow: const [
BoxShadow(
color: Colors.black12,
offset: Offset(0, 3),
spreadRadius: 3,
blurRadius: 3,
)
]),
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
ListTile(
visualDensity:
const VisualDensity(horizontal: -4, vertical: 0),
title: Text(_task.fileName ?? ""),
subtitle: labelStatus,
trailing: trailingIcon,
),
const SizedBox(height: 25.0),
Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("${_offset ~/ 1024} Kb / ${_total ~/ 1024} Kb",
textAlign: TextAlign.right),
Text("${_progress.floor()} %",
textAlign: TextAlign.right),
],
),
const SizedBox(height: 5),
LinearProgressIndicator(
value: _progress / 100,
)
],
),
),
],
),
),
),
),
);
}
Future<void> init() async {
final pathFile = (await path.getExternalStorageDirectory())!.path;
if (!mounted) return;
_task = _task.copyWith(
downloadPath: pathFile,
);
_downloader = SimpleDownloader.init(task: _task);
_downloader.callback.addListener(() {
setState(() {
_progress = _downloader.callback.progress;
_status = _downloader.callback.status;
_total = _downloader.callback.total;
_offset = _downloader.callback.offset;
});
});
}
Widget get labelStatus {
switch (_status) {
case DownloadStatus.undefined:
return const Text("等待中...");
case DownloadStatus.completed:
return const Text("下载完成");
case DownloadStatus.failed:
return const Text("下载失败");
case DownloadStatus.paused:
return const Text("下载暂停");
case DownloadStatus.deleted:
return const Text("文件已删除");
case DownloadStatus.canceled:
return const Text("下载取消");
default:
return const Text("正在下载");
}
}
Widget? get trailingIcon {
if (_status == DownloadStatus.undefined ||
_status == DownloadStatus.deleted) {
return IconButton(
splashRadius: 20,
onPressed: () => _downloader.download(),
constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
icon: const Icon(
Icons.play_arrow,
),
);
}
if (_status == DownloadStatus.running ||
_status == DownloadStatus.resume ||
_status == DownloadStatus.retry) {
return Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
IconButton(
splashRadius: 20,
onPressed: () => _downloader.pause(),
constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
icon: const Icon(
Icons.pause,
color: Colors.green,
),
),
IconButton(
splashRadius: 20,
onPressed: () => _downloader.cancel(),
constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
icon: const Icon(
Icons.close,
color: Colors.red,
),
),
],
);
}
if (_status == DownloadStatus.paused) {
return Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
IconButton(
splashRadius: 20,
onPressed: () => _downloader.resume(),
constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
icon: const Icon(
Icons.play_arrow,
color: Colors.blue,
),
),
IconButton(
splashRadius: 20,
onPressed: () => _downloader.cancel(),
constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
icon: const Icon(
Icons.close,
color: Colors.red,
),
),
],
);
}
if (_status == DownloadStatus.completed) {
return Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
IconButton(
tooltip: "打开文件",
splashRadius: 20,
onPressed: () async {
_downloader.open().then(
(isSuccess) {
if (!isSuccess!) {
showMessage(context, "无法打开下载的文件。");
}
},
);
},
constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
icon: const Icon(
Icons.file_open,
color: Colors.green,
),
),
IconButton(
tooltip: "删除文件",
splashRadius: 20,
onPressed: () => _downloader.delete(),
constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
icon: const Icon(
Icons.delete,
color: Colors.red,
),
),
],
);
}
if (_status == DownloadStatus.failed ||
_status == DownloadStatus.canceled) {
return Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
IconButton(
splashRadius: 20,
onPressed: () => _downloader.retry(),
constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
icon: const Icon(
Icons.refresh,
color: Colors.green,
),
),
IconButton(
splashRadius: 20,
onPressed: () => _downloader.restart(),
constraints: const BoxConstraints(minHeight: 32, minWidth: 32),
icon: const Icon(
Icons.restart_alt,
color: Colors.red,
),
),
]);
}
return null;
}
Future<void> showMessage(
BuildContext context,
String message,
) async {
final size = MediaQuery.of(context).size;
return showModalBottomSheet(
elevation: 2,
isDismissible: false,
enableDrag: false,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30), topRight: Radius.circular(30)),
),
context: context,
builder: (builder) {
return SizedBox(
height: 250,
child: Stack(children: [
Positioned(
top: 10,
right: 10,
child: IconButton(
splashRadius: 25,
onPressed: () => Navigator.pop(context),
icon: const Icon(
Icons.close,
size: 25,
),
),
),
Center(
child: Container(
constraints: BoxConstraints(
maxWidth: 0.8 * size.width,
),
child: Text(
message,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
),
),
Positioned(
bottom: 20,
right: 20,
left: 20,
child: ElevatedButton(
child: const Text(
"确定",
style: TextStyle(
color: Colors.white, fontWeight: FontWeight.w600),
),
onPressed: () => Navigator.pop(context),
),
),
]),
);
});
}
}
开始下载
要开始下载,请调用download()
方法:
_downloader.download();
暂停下载
要暂停下载,请调用pause()
方法:
_downloader.pause();
恢复下载
要恢复下载,请调用resume()
方法:
_downloader.resume();
取消下载
要取消下载,请调用cancel()
方法:
_downloader.cancel();
重试下载
要重试下载,请调用retry()
方法:
_downloader.retry();
重新启动下载
要重新启动下载,请调用restart()
方法:
_downloader.restart();
打开下载的文件(仅支持Android)
如果下载成功并希望打开文件,请调用open()
方法:
_downloader.open().then(
(isSuccess) {
if (!isSuccess!) {
print(context, "Failed to open downloaded file.");
}
},
);
Android集成
为了处理点击事件以打开下载的文件,你需要进行一些额外的配置。在AndroidManifest.xml
中添加以下内容:
<application>
...
<provider
android:name="adry.app.simple_downloader.FileProvider"
android:authorities="${applicationId}.simple_downloader.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_path"/>
</provider>
<application>
如果你的应用需要安装APK文件,还需要添加以下权限:
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
更多关于Flutter文件下载管理插件simple_downloader的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter文件下载管理插件simple_downloader的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用simple_downloader
插件来进行文件下载管理的示例代码。这个插件提供了在后台下载文件的功能,并支持暂停和恢复下载。
首先,确保你的Flutter项目已经添加了simple_downloader
依赖。在你的pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
simple_downloader: ^x.y.z # 请替换为最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,以下是一个完整的示例代码,展示如何使用simple_downloader
进行文件下载管理:
import 'package:flutter/material.dart';
import 'package:simple_downloader/simple_downloader.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Downloader Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final SimpleDownloader _downloader = SimpleDownloader();
String _downloadStatus = "No download started.";
@override
void initState() {
super.initState();
// 初始化下载器
_downloader.initialize().then((_) {
// 监听下载状态变化
_downloader.downloadStatusStream.listen((status) {
setState(() {
_downloadStatus = status;
});
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Downloader Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
_downloadStatus,
style: TextStyle(fontSize: 20),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
// 获取应用文档目录
Directory appDocDir = await getApplicationDocumentsDirectory();
String filePath = appDocDir.path + "/example.zip";
// 开始下载
var taskId = await _downloader.start(
url: "https://example.com/largefile.zip",
savedDir: appDocDir.path,
fileName: "example.zip",
showNotification: true,
openFileFromNotification: true,
);
setState(() {
_downloadStatus = "Download started with taskId: $taskId";
});
},
child: Text('Start Download'),
),
],
),
),
);
}
@override
void dispose() {
// 释放资源
_downloader.dispose();
super.dispose();
}
}
代码说明:
- 依赖安装:在
pubspec.yaml
文件中添加simple_downloader
依赖。 - 初始化下载器:在
initState
方法中初始化下载器并监听下载状态变化。 - 开始下载:点击按钮时,获取应用文档目录并调用
_downloader.start
方法开始下载文件。 - 显示下载状态:通过
_downloader.downloadStatusStream
监听下载状态并更新UI。
注意事项:
- 确保你提供的URL是有效的,并且服务器支持断点续传,因为
simple_downloader
依赖于这个功能来实现暂停和恢复下载。 - 根据需要调整文件保存路径和文件名。
- 在实际项目中,你可能需要处理更多的错误情况和用户交互,比如下载失败时的重试机制。
这个示例展示了基本的文件下载管理功能,你可以根据实际需求进行扩展和修改。