【发布时间】:2021-01-06 22:34:30
【问题描述】:
我正在使用 Bloc 包来更新 Flutter 应用程序上的小部件。我尝试更新一个变量,它是收藏夹列表。为此,我获取状态并将其修改为新值,然后生成新值(状态)。结果是在当前页面中看不到反映的更改,但在克隆状态下工作(因为它已正确加载到新标签中)。我做错了什么,因为我看不到当前状态中反映的变化,但能够在克隆中做到这一点?如果有不清楚的地方,请告诉我,或者我应该从我的代码库中分享其他内容。
更新 1:如果我手动执行热重载,我可以看到更改,但我想自动完成。
主状态
import 'package:meta/meta.dart' show required;
import 'package:documentales_app/models/youtube_video.dart';
import 'package:equatable/equatable.dart';
class MasterState extends Equatable {
final int currentTab;
final List<YoutubeVideo> history;
final List<YoutubeVideo> favorites;
MasterState(
{@required this.currentTab, @required this.history, this.favorites});
static MasterState initialState() =>
MasterState(currentTab: 0, history: [], favorites: []);
MasterState copyWith(
{int currentTab,
List<YoutubeVideo> history,
List<YoutubeVideo> favorites}) {
return MasterState(
currentTab: currentTab ?? this.currentTab,
history: history ?? this.history,
favorites: favorites ?? this.favorites);
}
@override
List<Object> get props => [currentTab, history, favorites];
}
大师组
Stream<MasterState> _toggleInFavorites(MasterToggleInFavorites event) async* {
final int index = this
.state
.favorites
.indexWhere((item) => item.videoId == event.youtubeVideo.videoId);
if (index == -1) {
final favorites = List<YoutubeVideo>.from(this.state.favorites);
favorites.add(event.youtubeVideo);
event.youtubeVideo.isFavorite = true;
yield this.state.copyWith(favorites: favorites);
} else {
final favorites = List<YoutubeVideo>.from(this.state.favorites);
favorites.removeAt(index);
event.youtubeVideo.isFavorite = false;
yield this.state.copyWith(favorites: favorites);
}
}
切换按钮
CupertinoButton(
padding: EdgeInsets.zero,
minSize: 30,
onPressed: () {
masterBloc.add(MasterToggleInFavorites(item));
},
child: CircleContainer(
child: Icon(
//Icons.playlist_add,
item.isFavorite
? Icons.favorite
: Icons.favorite_border,
color: Colors.white,
),
size: 35,
),
),
收藏标签
import 'package:cached_network_image/cached_network_image.dart';
import 'package:documentales_app/blocs/pages/master_bloc/master_bloc.dart';
import 'package:documentales_app/blocs/pages/master_bloc/master_events.dart';
import 'package:documentales_app/models/youtube_video.dart';
import 'package:share/share.dart';
import 'package:documentales_app/widgets/circle_container.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_youtube/flutter_youtube.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../utils/keys.dart';
class YoutubeVideoItem extends StatelessWidget {
final VoidCallback onDismissed;
final YoutubeVideo item;
const YoutubeVideoItem({@required this.item, this.onDismissed})
: assert(item != null);
Widget _getView(MasterBloc masterBloc) {
return Container(
child: CupertinoButton(
padding: EdgeInsets.zero,
onPressed: () {
masterBloc.add(MasterAddToHistory(item));
FlutterYoutube.playYoutubeVideoByUrl(
apiKey: API_KEY,
videoUrl: "https://www.youtube.com/watch?v=${item.videoId}",
autoPlay: true, //default falase
fullScreen: true //default false
);
},
child: AspectRatio(
aspectRatio: 12 / 3,
child: Container(
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.greenAccent,
boxShadow: [
BoxShadow(color: Colors.black26, blurRadius: 5),
],
),
child: Row(
children: [
Expanded(
flex: 4,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: CachedNetworkImage(
imageUrl: item.banner,
fit: BoxFit.cover,
height: double.infinity,
),
),
),
Expanded(
flex: 5,
child: Container(
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
item.title,
maxLines: 2,
style: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.white,
fontSize: 14),
),
SizedBox(
height: 5,
),
Expanded(
child: Text(
item.description,
overflow: TextOverflow.fade,
style: TextStyle(
fontWeight: FontWeight.w300,
color: Colors.grey[600],
fontSize: 13),
),
),
],
),
),
),
Expanded(
flex: 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CupertinoButton(
padding: EdgeInsets.zero,
minSize: 30,
onPressed: () {
masterBloc.add(MasterToggleInFavorites(item));
},
child: CircleContainer(
child: Icon(
//Icons.playlist_add,
item.isFavorite
? Icons.favorite
: Icons.favorite_border,
color: Colors.white,
),
size: 35,
),
),
CupertinoButton(
padding: EdgeInsets.zero,
minSize: 30,
onPressed: () {
Share.share(
'https://www.youtube.com/watch?v=${item.videoId}',
subject: 'Mira este impresionante documental');
},
child: CircleContainer(
child: Icon(
Icons.share,
color: Colors.white,
),
size: 35,
),
),
],
),
),
],
),
),
),
),
);
}
@override
Widget build(BuildContext context) {
final masterBloc = BlocProvider.of<MasterBloc>(context);
if (onDismissed != null) {
return Dismissible(
key: Key(item.videoId),
onDismissed: (_) {
if (onDismissed != null) {
onDismissed();
}
},
child: _getView(masterBloc),
);
}
return _getView(masterBloc);
}
}
主页标签
import 'package:cached_network_image/cached_network_image.dart';
import 'package:documentales_app/api/account_api.dart';
import 'package:documentales_app/api/youtube_api.dart';
import 'package:documentales_app/models/play_list.dart';
import 'package:documentales_app/models/youtube_video.dart';
import 'package:documentales_app/pages/home_page_widgets/home_tab_shimmer.dart';
import 'package:documentales_app/pages/home_page_widgets/new_videos.dart';
import 'package:documentales_app/pages/home_page_widgets/top_play_lists.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../../utils/keys.dart';
class HomeTab extends StatefulWidget {
@override
_HomeTabState createState() => _HomeTabState();
}
class _HomeTabState extends State<HomeTab> {
AccountApi _accountApi = AccountApi();
YoutubeApi _youtubeApi = YoutubeApi(apiKey: API_KEY);
List<dynamic> _users = [];
List<PlayList> _playlists = [];
List<YoutubeVideo> _newVideos = [];
bool _isLoading = true;
@override
void initState() {
super.initState();
_load();
}
_load() async {
final users = await _accountApi.getUsers(1);
final List<PlayList> playLists =
await _youtubeApi.getPlaylists('jklnvfyyklhjh');
final List<YoutubeVideo> newVideos = await _youtubeApi
.getPlaylistVideos('PLFXLg_sbbjkGKJbkjgkkGKkgk');
setState(() {
_users.addAll(users);
_playlists.addAll(playLists);
_newVideos.addAll(newVideos);
_isLoading = false;
});
}
@override
Widget build(BuildContext context) {
return ListView(
children: [
_isLoading
? HomeTabShimmer()
: Column(
children: [
TopPlayLists(items: _playlists),
SizedBox(height: 10),
NewVideos(
items: _newVideos,
),
SizedBox(height: 5),
],
)
],
);
}
}
【问题讨论】:
标签: flutter bloc flutter-bloc