老师,请教个问题initState方法重复调用的问题
来源:6-4 轮播图Banner组件封装

Kevin_Choi
2021-05-06
老师,请教个问题:
点击HomeTabPage页面的 banner 进入 VideoDetailPage页面,为什么都会调用 BottomNavigator 的 initState 方法,我认为不应该重新创建的?
在VideoDetailPage页面点击 左上角 返回icon,为什么会调用 HomePage 的 initState 方法?应该已经创建过了,不应该重新创建了
import 'package:flutter/material.dart';
import 'package:vione_bll/navigator/hi_navigator.dart';
import 'package:vione_bll/page/index/favorite_page.dart';
import 'package:vione_bll/page/index/home_page.dart';
import 'package:vione_bll/page/index/profile_page.dart';
import 'package:vione_bll/page/index/ranking_page.dart';
import 'package:vione_bll/utils/color.dart';
class BottomNavigator extends StatefulWidget {
@override
_BottomNavigatorState createState() => _BottomNavigatorState();
}
class _BottomNavigatorState extends State<BottomNavigator>
with AutomaticKeepAliveClientMixin {
final Color _defaultColor = Colors.grey;
final Color _activeColor = primary;
int _current = 0;
final PageController _controller = PageController(initialPage: 0);
List<Widget> _pages;
bool _hasBuild = false;
@override
void initState() {
super.initState();
print("---_BottomNavigatorState---initState");
}
@override
Widget build(BuildContext context) {
super.build(context);
_pages = [HomePage(), RankingPage(), FavoritePage(), ProfilePage()];
if (!_hasBuild) {
HiNavigator.getInstance().onBottomTagChange(_current, _pages[_current]);
_hasBuild = true;
}
return Scaffold(
body: PageView(
controller: _controller,
children: _pages,
onPageChanged: (index) {
HiNavigator.getInstance().onBottomTagChange(index, _pages[index]);
this.setState(() {
this._current = index;
});
},
physics: NeverScrollableScrollPhysics(),
),
bottomNavigationBar: BottomNavigationBar(
onTap: (index) {
_controller.jumpToPage(index); //回调用PageView的onPageChanged方法
// HiNavigator.getInstance().onJumpTo(RouteStatus.detail, args: {"videoMo": VideoMo(vid: "112")});
},
type: BottomNavigationBarType.fixed,
items: [
_bottomItem('首页', Icons.home, 0),
_bottomItem('排行', Icons.local_fire_department, 1),
_bottomItem('收藏', Icons.favorite, 2),
_bottomItem('我的', Icons.live_tv, 3)
],
currentIndex: _current,
unselectedItemColor: _defaultColor,
selectedItemColor: _activeColor,
),
);
}
_bottomItem(String title, IconData iconData, int index) {
return BottomNavigationBarItem(
icon: Icon(
iconData,
color: _defaultColor,
),
activeIcon: Icon(
iconData,
color: _activeColor,
),
label: title);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
bool get wantKeepAlive => true;
}
import 'package:flutter/material.dart';
import 'package:vione_bll/core/hi_state.dart';
import 'package:vione_bll/dao/home_dao.dart';
import 'package:vione_bll/http/core/hi_error.dart';
import 'package:vione_bll/modle/home_mo.dart';
import 'package:vione_bll/navigator/hi_navigator.dart';
import 'package:vione_bll/page/index/home_tab_page.dart';
import 'package:vione_bll/utils/color.dart';
import 'package:vione_bll/utils/toast.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends HiState<HomePage>
with AutomaticKeepAliveClientMixin, TickerProviderStateMixin {
RouteChangeListener _listener;
TabController _controller;
List<BannerMo> bannerList = [];
List<CategoryMo> categoryList = [];
@override
void initState() {
print("---_HomePageState -initState-----");
super.initState();
_controller = TabController(length: categoryList.length, vsync: this);
// HiNavigator.getInstance().addListener(this._listener = (current, pre) {
// print('home:current:${current.page}');
// print('home:pre:${pre.page}');
// if (widget == current.page || current.page is HomePage) {
// print('打开了首页:onResume');
// } else if (widget == pre?.page || pre?.page is HomePage) {
// print('首页:onPause');
// }
// });
loadData();
}
@override
void dispose() {
HiNavigator.getInstance().removeListener(_listener);
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
super.build(context);
return Scaffold(
body: Column(
children: [
Container(
color: Colors.white,
padding: EdgeInsets.only(top: 30),
child: _tabBar(),
),
Flexible(
child: TabBarView(
controller: _controller,
children: categoryList.map((tab) {
return HomeTabPage(
name: tab.name,
bannerList: tab.name == '推荐' ? bannerList : null,
);
}).toList()),
),
],
),
);
}
@override
bool get wantKeepAlive => true;
_tabBar() {
return TabBar(
controller: _controller,
isScrollable: true,
labelColor: Colors.black,
indicator: UnderlineTabIndicator(
borderSide: BorderSide(color: primary, width: 3),
insets: EdgeInsets.only(left: 20, right: 20),
),
tabs: categoryList.map<Tab>(
(tab) {
return Tab(
child: Padding(
padding: EdgeInsets.only(left: 5, right: 5),
child: Text(
tab.name,
style: TextStyle(fontSize: 16, color: Colors.black),
),
),
);
},
).toList());
}
void loadData() async {
try {
HomeMo ret = await HomeDao.get('推荐');
if (ret.categoryList != null) {
_controller =
TabController(length: ret.categoryList.length, vsync: this);
}
this.setState(() {
categoryList = ret.categoryList;
bannerList = ret.bannerList;
});
} on NeedAuth catch (e) {
showWarnToast(e.message);
} on HiNetError catch (e) {
showWarnToast(e.message);
}
}
}
import 'package:flutter/material.dart';
import 'package:vione_bll/modle/home_mo.dart';
import 'package:vione_bll/widget/hi_banner.dart';
class HomeTabPage extends StatefulWidget {
final String name;
final List<BannerMo> bannerList;
const HomeTabPage({Key key, this.name, this.bannerList}) : super(key: key);
@override
_HomeTabPageState createState() => _HomeTabPageState();
}
class _HomeTabPageState extends State<HomeTabPage>
with AutomaticKeepAliveClientMixin {
@override
Widget build(BuildContext context) {
super.build(context);
return Container(
child: ListView(
children: [
if (widget.bannerList != null) _banner(),
],
),
);
}
_banner() {
return Padding(
padding: EdgeInsets.only(left: 8, right: 8),
child: HiBanner(widget.bannerList),
);
}
@override
bool get wantKeepAlive => true;
}
import 'package:flutter/material.dart';
import 'package:vione_bll/modle/home_mo.dart';
class VideoDetailPage extends StatefulWidget {
final Map args;
const VideoDetailPage({
Key key,
this.args,
}) : super(key: key);
@override
_VideoDetailPageState createState() => _VideoDetailPageState();
}
class _VideoDetailPageState extends State<VideoDetailPage> {
@override
void initState() {
super.initState();
print("---_VideoDetailPageState -- initState");
}
@override
Widget build(BuildContext context) {
VideoMo videoMo = widget.args['videoMo'];
return Scaffold(
appBar: AppBar(),
body: Container(
child: Text("视频详情页: vid: ${videoMo.vid}"),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:vione_bll/dao/login_dao.dart';
import 'package:vione_bll/db/hi_cache.dart';
import 'package:vione_bll/navigator/bottom_navigator.dart';
import 'package:vione_bll/navigator/hi_navigator.dart';
import 'package:vione_bll/page/launcher/login_page.dart';
import 'package:vione_bll/page/launcher/registration_page.dart';
import 'package:vione_bll/page/video_detail_page.dart';
import 'package:vione_bll/utils/color.dart';
import 'package:vione_bll/utils/toast.dart';
void main() {
runApp(BiliApp());
}
class BiliApp extends StatefulWidget {
@override
_BiliAppState createState() => _BiliAppState();
}
class _BiliAppState extends State<BiliApp> {
BiliRouterDelegate _routerDelegate = BiliRouterDelegate();
@override
Widget build(BuildContext context) {
print("BiliApp -- build");
return FutureBuilder<HiCache>(
//进行初始化
future: HiCache.preInit(),
builder: (BuildContext context, AsyncSnapshot<HiCache> snapshot) {
//定义路由
var widget = snapshot.connectionState == ConnectionState.done
? Router(
routerDelegate: _routerDelegate,
)
: Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
return MaterialApp(
home: widget,
theme: ThemeData(
primarySwatch: white,
),
);
},
);
}
}
class BiliRouterDelegate extends RouterDelegate<BiliRoutePath>
with ChangeNotifier, PopNavigatorRouterDelegateMixin<BiliRoutePath> {
//为Navigator设置一个key,必要的时候可以通过navigatorKey.currentState来获取到NavigatorState对象
@override
GlobalKey<NavigatorState> get navigatorKey => GlobalKey();
BiliRouterDelegate() {
HiNavigator.getInstance().registerRouteJump(
RouteJumpListener((RouteStatus routeStatus, {Map args}) {
_routeStatus = routeStatus;
this.args = args;
notifyListeners();
}));
}
List<MaterialPage> pages = [];
RouteStatus _routeStatus = RouteStatus.home;
Map args;
RouteStatus get routeStatus {
if (_routeStatus != RouteStatus.registration && !hasLogin) {
_routeStatus = RouteStatus.login;
}
return _routeStatus;
}
bool get hasLogin => LoginDao.getBoardingPass() != null;
@override
Widget build(BuildContext context) {
print("BiliRouterDelegate -- build");
int index = getPageIndex(pages, routeStatus);
List<MaterialPage> tempPages = pages;
if (index != -1) {
///要打开的页面在栈中已存在,则将该页面和它上面的所有页面都出栈
///tips 具体规则可以根据需要进行调整,这里要求栈中只允许有一个同样的页面的实例
tempPages = tempPages.sublist(0, index);
}
var page;
if (routeStatus == RouteStatus.home) {
//跳转首页时,将栈中其它页面进行出栈,因为首页不可回退
pages.clear();
page = pageWrap(
BottomNavigator(),
);
} else if (routeStatus == RouteStatus.detail) {
page = pageWrap(VideoDetailPage(args: args));
} else if (routeStatus == RouteStatus.registration) {
page = pageWrap(RegistrationPage());
} else if (routeStatus == RouteStatus.login) {
page = pageWrap(LoginPage());
}
//重建一个数组,否则pages因引用没有改变路由不会生效
tempPages = [...tempPages, page];
//通知路由信息变化
HiNavigator.getInstance().notify(tempPages, pages);
pages = tempPages;
return WillPopScope(
child: Navigator(
key: navigatorKey,
pages: pages,
onPopPage: (route, result) {
if (route.settings is MaterialPage) {
//登录页未登录,返回拦截
if ((route.settings as MaterialPage).child is LoginPage) {
if (!hasLogin) {
showWarnToast("请先登录");
return false;
}
}
}
//执行返回操作
if (!route.didPop(result)) {
return false;
}
var tempPages = [...pages];
//进行出栈
pages.removeLast();
//通知路由信息变化
HiNavigator.getInstance().notify(pages, tempPages);
return true;
},
),
onWillPop: () async => !await navigatorKey.currentState.maybePop(),
);
}
@override
void addListener(listener) {
print("BiliRouterDelegate -- addListener");
super.addListener(listener);
}
@override
Future<bool> popRoute() {
print("BiliRouterDelegate -- popRoute");
return super.popRoute();
}
@override
void dispose() {
print("BiliRouterDelegate -- dispose");
super.dispose();
}
@override
Future<void> setNewRoutePath(BiliRoutePath configuration) async {
print("BiliRouterDelegate -- setNewRoutePath");
}
}
class BiliRoutePath {
final String location;
BiliRoutePath.home() : location = "/";
BiliRoutePath.detail() : location = "/detail";
}
写回答
1回答
-
CrazyCodeBoy
2021-05-07
运行了课程源码看了下没发现有多次调用initState的情况,有没有对照下这块课程源码检查下你的代码实现看是否有出入的地方呢
00
相似问题