我创建了一个带有列表的Flutter应用程序。轻按一个项目,即可打开该项目的详细信息。
问题是,每当我从详细信息屏幕返回时,都会重新加载列表屏幕。我不想每次都重新加载列表。
我在此使用了BloC架构。
下面是代码段。请提出建议。
谢谢。
主要
void main() {
final userRepository = UserRepository();
ApiClient apiClient = ApiClient(httpClient: http.Client());
runApp(BlocProvider<AuthenticationBloc>(
builder: (context) {
return AuthenticationBloc(
userRepository: userRepository, apiClient: apiClient)
..dispatch(AppStarted());
},
child: MyApp(userRepository: userRepository),
));
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
final UserRepository userRepository;
MyApp({Key key, @required this.userRepository}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
bloc: BlocProvider.of<AuthenticationBloc>(context),
builder: (context, state) {
if (state is AuthenticationUninitialized) {
return SplashPage();
}
if (state is AuthenticationAuthenticated) {
return HomePage(userRepository: userRepository);
}
if (state is AuthenticationUnauthenticated) {
return LoginPage(userRepository: userRepository);
}
if (state is AuthenticationLoading) {
return LoadingIndicator();
}
return null;
},
),
);
}
}
列表屏幕
class HomePage extends StatelessWidget {
UserRepository userRepository;
HomePage({@required this.userRepository}) : super();
@override
Widget build(BuildContext context) {
ApiClient apiClient = ApiClient(httpClient: http.Client());
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
drawer: AppDrawer(userRepository),
body: BlocProvider(
builder: (context) {
return HomeBloc(apiClient);
},
child: _HomeContent(),
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
backgroundColor: Colors.amberAccent,
),
);
}
}
class _HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
final HomeBloc homeBloc = BlocProvider.of<HomeBloc>(context);
homeBloc.dispatch(FetchMovieList());
return BlocBuilder<HomeBloc, HomeState>(
builder: (context, state) {
if (state is MovieListLoading) {
return Center(
child: CircularProgressIndicator(),
);
}
if (state is MovieListLoaded) {
List<Movie> topRatedMovies = state.movieList;
return new ListView.builder(
itemBuilder: (BuildContext context, int index) {
return new ListTile(
title: Card(
child: Row(
children: <Widget>[
Image.network(ApiClient.IMAGE_BASE_URL +
topRatedMovies[index].poster_path),
Column(
children: <Widget>[
Text(topRatedMovies[index].title),
],
)
],
),
),
onTap: () {
_onListItemTapped(topRatedMovies[index].id, context);
},
);
},
itemCount: topRatedMovies.length,
);
}
if (state is MovieListError) {
return Center(
child: Text('Error in calling API'),
);
}
return Center(child: Text('Employee data not found'));
},
);
}
void _onListItemTapped(int movieId, BuildContext context) {
Navigator.push(context,
MaterialPageRoute(
builder: (context) => MovieDetailPage(
movieId: movieId,
)));
}
}
答案 0 :(得分:0)
任何时候您的构建方法都需要准备好进行多个构建调用。如果构建调用引起问题,则可能是错误的。最好在build方法之外获取数据,以防止不必要的API调用。
例如,您可以创建一个有状态窗口小部件,并在 initState 方法中可以获取数据。之后,将调用build方法以使用数据准备UI。您可以使用Future Builder显示进度并在获取数据时更新UI。
示例:
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
Future _future;
Future getData() async {
// Fetch data
}
@override
void initState() {
super.initState();
_future = getData();
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: _future,
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
default:
if (snapshot.data.hasErrors) {
return Text('Error: ${snapshot.data.errors}');
} else {
// Data is fetched, build UI
return ListTile();
}
}
});
}
}