我有一个Flutter应用,它显示了网络视频文件的视频列表视图。
我有一个功能 downloadFile(),该功能可将每个视频下载到本地存储,并使用下载文件的信息更新共享的首选项。
这一切都很好,但是,当我使用BottomNavigationBar导航到应用程序中的另一个页面时,我的下载过程中断了,所有信息都丢失了。
我知道这是因为所有下载逻辑都处于VideoListPage状态。
我怎样才能使下载在全局类中进行?我是否需要使用状态管理系统,还是有一种更简便的方法来不丢失下载文件的状态?
谢谢..
main_scafold.dart
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'video_list_page.dart';
import 'podcasts.dart';
import 'my_experience.dart';
//this page is the homescreen
class MainScafold extends StatefulWidget {
static const String id = 'video_list';
@override
createState() => MainScafoldState();
}
class MainScafoldState extends State<MainScafold> {
int _selectedIndex = 0;
static const TextStyle optionStyle =
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
List<Widget> _widgetOptions = <Widget>[
VideoListPage(),
Podcasts(),
MyExperience(),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('News'),
),
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
title: Text('Business'),
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
title: Text('School'),
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
);
}
}
video_list.dart
import 'dart:convert';
import 'package:networking_demo/models/download_video.dart';
import 'dart:io';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/material.dart';
import 'package:networking_demo/screens/video_player.dart';
import 'package:networking_demo/models/newsArticle.dart';
import 'package:networking_demo/models/blog_json.dart';
import 'package:http/http.dart' as http;
import 'series_index.dart';
import 'package:networking_demo/models/all_videos.dart';
import 'package:networking_demo/models/single_video.dart';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';
import 'package:percent_indicator/percent_indicator.dart';
// This is the screen for all the episodes of Presenter
class VideoListPage extends StatefulWidget {
@override
_VideoListPageState createState() => _VideoListPageState();
}
class _VideoListPageState extends State<VideoListPage> {
bool result = false;
List<NewsArticle> _newsArticles = List<NewsArticle>();
List<Datum> _blogs = List<Datum>();
List<DatumVideo> _videos = List<DatumVideo>();
double downloadPercent = 0;
bool downloading = false;
//var progressString = "";
Future<void> downloadFile(
{int currentIndex, title, description, image, videoKey}) async {
final prefs = await SharedPreferences.getInstance();
Dio dio = Dio();
String downloadURL;
var dir = await getApplicationDocumentsDirectory();
var localURL = dir.path + '/$videoKey.mp4';
print('the directory is: ${dir.path}');
print('the local url is: $localURL');
try {
await http
.get('https://platform.seebenow.com/v1/videos/${videoKey}', headers: {
"Brand-ID": "2",
HttpHeaders.authorizationHeader:
"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjIzMTljMWZlMTk4YzM4NTg5ZDJlMjJlYWM5MGZiMDAwZDdiNDZlZWUxMmVkYjcyMWJiZWI0ZDliMDU1ZTA2NjIyOGI2Njc4YTBmMjA3ZGQyIn0.eyJhdWQiOiIyIiwianRpIjoiMjMxOWMxZmUxOThjMzg1ODlkMmUyMmVhYzkwZmIwMDBkN2I0NmVlZTEyZWRiNzIxYmJlYjRkOWIwNTVlMDY2MjI4YjY2NzhhMGYyMDdkZDIiLCJpYXQiOjE1NzQzNjExOTgsIm5iZiI6MTU3NDM2MTE5OCwiZXhwIjoxNjA1OTgzNTk4LCJzdWIiOiIyNDgyMCIsInNjb3BlcyI6W119.bmNtFzdkld680ADMsohupkETnSh5H03a3sFjYCwiBAipRJrc0FxGAyqNdrpvMUcMMQaqoEEGIDvmfUYdSMknsLVo5AzSQygFTHXQH31BX43JAjcAm3BVGZLueTouNVAstY1C0PIEZ7POxhUEeRNMPEb5zZ8WrNWw7c8YEv1QqcoM13p5zljd7ryxzMxXzF5BaEQr5CDzjWFmXeR-WTyqYmzsXL83s_ESQ1TqetShZD1hahdZnAYpoXsJNU3AnPgPL5zELWtmsJyV4dWqq0GCdQ6dnIaP-livG4KZG-8xR2PYOgjXRkJu2avBtvmqSm7oQQFQa9svqba2YVKiBpSrrVPYKucGepKavTjAeIGrb96OuhB0aToV0RZv7tvgB2A1LLZRLIMHC4zvjhfoqTyEMwMCWCiT7MAi4ODN5kY6DVUOp35YSBVKGkF3Q6aV0NLmWSUbdW3yT5QHTnoVWmTm3EAKRR-lguvGZRzhACjyJEavZ-LXqqE7ay-LwjbeIcq8FFg2UtEyQ5V2ltXwpKVcXEs8zHsvJZFFS6_oNsBg08kTQNrFcrlpm6NzyCG-_-bXr9AtW3DqtThlCE45T3kieFtupDSwli2IIaE8fucd45cfAtwBQVOYgeuwdqG1-ZpxuahjgvG6qxuGFfEDWyFyeed2QI6pbTzoBzL6WJ7zYHs"
}).then((response) {
downloadURL = videoFromJson(response.body).data.episodes[0].downloadUrl;
});
await dio.download(downloadURL, "${dir.path}/$videoKey.mp4",
onReceiveProgress: (rec, total) {
setState(() {
downloading = true;
_videos[currentIndex].videoProgress = (rec / total);
_videos[currentIndex].currentVisible = true;
// DownloadVideo['']
print(_videos[currentIndex].videoProgress.toString());
});
});
} catch (e) {
print(e);
}
print('the preferences is' + prefs.containsKey('videos').toString());
if (!prefs.containsKey('videos')) prefs.setString('videos', '');
print('localURL $localURL title $title videoKey $videoKey image $image');
String videoJson = prefs.getString('videos');
List<DownloadVideo> videoList;
print('is videos json empty? ${videoJson.isEmpty}');
if (videoJson.isEmpty) {
videoList = [];
} else {
videoList = downloadVideoFromJson(videoJson);
// print('this is the video list ${videoList.}');
}
videoList.add(
DownloadVideo(
title: title,
description: description,
videoKey: videoKey,
image: image,
localURL: localURL,
),
);
prefs.setString('videos', jsonEncode(videoList));
setState(() {
downloading = false;
});
print("Download completed");
}
void addInfo() async {
final prefs = await SharedPreferences.getInstance();
//print(prefs.containsKey('videos'));
String videoJson = prefs.getString('videos');
prefs.setString('videos', '');
print(
'the video preferences is empty ${prefs.getString('videos').isEmpty}');
print(videoJson);
}
void _fetchVideos() {
http.get('https://platform.seebenow.com/v1/episodes/search?type=video',
headers: {"Brand-ID": "2"}).then((response) {
setState(() {
_videos = videosFromJson(response.body).data;
print(_videos[0].title);
result = true;
});
});
}
void _fetchBlogs() {
http.get('https://platform.seebenow.com/v1/blogs?page=1',
headers: {"Brand-ID": "2"}).then((response) {
setState(() {
_blogs = blogFromJson(response.body).data;
print(_blogs[0].content.toString());
});
});
}
@override
void initState() {
super.initState();
_fetchVideos();
_fetchBlogs();
}
Widget _buildBlog(BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
),
padding: EdgeInsets.all(10.0),
width: 250.0,
height: 80,
child: Text(
'"' + _blogs[index].content + ' " ',
style: TextStyle(fontSize: 13),
),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Flexible(
flex: 1,
child: Container(
color: Colors.grey.shade300,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: _blogs.length,
itemBuilder: _buildBlog,
),
),
),
Flexible(
flex: 5,
child: DefaultTabController(
length: 2,
child: Column(
children: <Widget>[
Container(
color: Colors.green,
child: TabBar(
tabs: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Episodes'),
Tab(
icon: Icon(Icons.directions_car),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Series'),
Tab(
icon: Icon(Icons.directions_car),
),
],
),
],
),
),
Expanded(
child: Container(
color: Colors.lightBlueAccent,
child: TabBarView(
children: [
BuildVideoList(),
SeriesIndex(),
],
),
),
),
],
),
),
),
],
),
);
}
Container BuildVideoList() {
if (result == false) {
return Container(
child: Center(
child: SizedBox(
child: CircularProgressIndicator(),
height: 50.0,
width: 50.0,
),
),
);
}
return Container(
color: Colors.grey.shade300,
child: ListView.builder(
itemCount: _videos.length,
itemBuilder: _buildItemsForListView,
),
);
}
Widget _buildItemsForListView(BuildContext context, int index) {
var progressVariable = _videos[index].videoProgress.toString();
var downloadText = Text('Download $progressVariable');
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
FlatButton(
onPressed: () {
Navigator.push(context,
MaterialPageRoute<void>(builder: (context) {
return HitomiVideoPlayer(
videoKey: _videos[index].videoId,
title: _videos[index].title);
}));
},
child: Stack(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Image.network(_videos[index].image),
),
Padding(
padding: const EdgeInsets.only(top: 60),
child: Center(
child: Align(
alignment: Alignment.bottomCenter,
child: Visibility(
visible: _videos[index].currentVisible,
child: CircularPercentIndicator(
radius: 50.0,
lineWidth: 6.0,
animation: false,
percent: _videos[index].videoProgress,
center: new Text(
(_videos[index].videoProgress * 100)
.toStringAsFixed(0),
style: new TextStyle(
fontWeight: FontWeight.bold, fontSize: 12.0),
),
circularStrokeCap: CircularStrokeCap.round,
progressColor: Colors.red,
),
),
),
),
),
],
),
),
Text(_videos[index].title, style: TextStyle(fontSize: 18)),
Padding(
padding: const EdgeInsets.all(12.0),
child: Text(_videos[index].description,
style: TextStyle(fontSize: 12)),
),
FlatButton(
onPressed: () {
downloadFile(
title: _videos[index].title,
description: _videos[index].description,
image: _videos[index].image,
videoKey: _videos[index].videoId,
currentIndex: index);
},
child: downloadText,
),
FlatButton(
onPressed: () {
addInfo();
},
child: Text('Add Info'),
)
],
),
);
}
}