导航到同一屏幕两次构建两个小部件

时间:2019-12-29 15:14:43

标签: flutter

我有一个应用程序,在首页中产品水平显示。点击产品后,将显示产品详细信息屏幕,其中有关产品的详细信息显示在不同的小部件中。

此详细信息屏幕还具有显示相关产品的水平滚动列表。轻触其中一个相关产品后,将显示相同详细信息屏幕的另一个实例。

问题

但是这里的问题是build方法被调用了两次。仅当我尝试查看相关产品的详细信息时(它在产品详细信息页面本身中列出),它两次调用。

这是Details屏幕中代码的一部分。

class Details extends StatefulWidget {
  // Declare a field that holds the Todo.
  final details;

  // In the constructor, require a Todo.
  Details({Key key, @required this.details}) : super(key: key);

  State<StatefulWidget> createState() {
    return _DetailsState(details);
  }
}


class _DetailsState extends State<Details> with SingleTickerProviderStateMixin {
  _DetailsState(details);

  YoutubePlayerController _ytcontroller;

  TabController _tabController;
  int _tabIndex = 0;

  Screen size;

  @override
  void dispose() {
    if (_ytcontroller != null) {
      _ytcontroller.dispose();
    }

    _tabController.dispose();
    super.dispose();
  }

  @override
  void initState() {
    super.initState();

    if (widget.details.videos != null) {
      String videoId;
      videoId = YoutubePlayer.convertUrlToId(widget.details.videos[0].url);

      _ytcontroller = YoutubePlayerController(
        initialVideoId: videoId,
        flags: YoutubePlayerFlags(
          mute: false,
          autoPlay: true,
          disableDragSeek: false,
          loop: false,
          isLive: false,
          forceHideAnnotation: true,
        ),
      );
      _tabController = TabController(length: 4, vsync: this);
    } else {
      _tabController = TabController(length: 3, vsync: this);
    }
    _tabController.addListener(_handleTabSelection);
  }

  _handleTabSelection() {
    if (_tabController.indexIsChanging) {
      setState(() {
        _tabIndex = _tabController.index;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    String wid = widget.details.itemId;
    //IF I PUT DEBUG MARKER ABOVE AND TAP RELATED PRODUCT FROM PRODUCT DETAILS PAGE
    //THIS BUILD METHOD GETS CALLED TWO TIMES, 
    // FIRST => wid = item id of clicked product 
    // SECOND => wid = item id of currently viewing product 

    size = Screen(MediaQuery.of(context).size);
    return Scaffold(
      resizeToAvoidBottomInset: false,
      backgroundColor: Constants.scaffoldColor,
      floatingActionButton: buildBoomMenu(widget.details),
      body: NestedScrollView(
        headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
          return <Widget>[
            SliverAppBar(
              expandedHeight: size.getSizePx(277),
              floating: false,
              title: const Text("Details"),
              pinned: true,
              flexibleSpace: Container(
                decoration: BoxDecoration(
                  gradient: LinearGradient(
                      begin: Alignment.topLeft,
                      end: Alignment.bottomRight,
                      colors: [Constants.gradientStart, Constants.gradientEnd]),
                ),
                child: FlexibleSpaceBar(
                  centerTitle: true,
                  background: Swiper(
                    itemBuilder: (BuildContext context, int index) {
                      return _cacheImageBuilder(
                          widget.details.images[index].thumb);
                    },
                    itemCount: widget.details.images.length,
                    pagination: new SwiperPagination(
                      alignment: Alignment.bottomCenter,
                      builder: FractionPaginationBuilder(
                        activeColor: Colors.white,
                        color: Colors.white70,
                        fontSize: size.getSizePx(16),
                        activeFontSize: size.getSizePx(20),
                      ),
                    ),
                    autoplay: true,
                    onTap: (index) {
                      Navigator.push(
                        context,
                        MaterialPageRoute(
                          builder: (context) => ImageViewer(
                            imglists: widget.details.images,
                            initialIndex: index,
                          ),
                        ),
                      );
                    },
                    autoplayDelay: 8000,
                    autoplayDisableOnInteraction: true,
                  ),
                ),
              ),
            ),
          ];
        },
        body: SingleChildScrollView(
          padding: EdgeInsets.only(
              left: size.getSizePx(10), right: size.getSizePx(10)),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            mainAxisSize: MainAxisSize.max,
            children: <Widget>[
              Container(
                //height: size.getSizePx(230),
                child: propertyDetails(),
              ),
              TabBar(
                controller: _tabController,
                labelStyle: TextStyle(fontSize: size.getSizePx(12)),
                labelColor: Constants.primaryColor,
                unselectedLabelColor: Colors.black45,
                indicatorColor: Constants.primaryColor,
                tabs: [
                  Tab(
                    text: "Seller Info",
                    icon: Icon(Constants.iconAccount),
                  ),
                  Tab(
                    text: "Details",
                    icon: Icon(Constants.iconDetails),
                  ),
                  Tab(text: "Video", icon: Icon(Constants.iconYoutube)),
                ],
              ),
              Container(
                child: [
                  Container(
                    margin: EdgeInsets.only(top: size.getSizePx(15)),
                    child: Column(
                      children: <Widget>[
                        //Show some widgets
                      ],
                    ),
                  ),
                  Container(
                    margin: EdgeInsets.only(top: size.getSizePx(15)),
                    child: Column(
                      children: <Widget>[
                        //show few widgets here
                      ],
                    ),
                  ),
                  Container(
                   //show videos
                  ),
                ][_tabIndex],
              ),
              const SizedBox(height: 20),
              RelatedProducts( //Another widget which fetches list of products related to product whose detail we are currently viewing
                deviceType: "mobile",
                model: widget.details.model,
                sku: widget.details.sku,
                category: widget.details.category,
                itemId: widget.details.itemId,
                brand: widget.details.brand,
              ),
              SizedBox(height: size.getSizePx(40)),
            ],
          ),
        ),
      ),
    );
  }
}

有人可以帮我吗?

1 个答案:

答案 0 :(得分:0)

build方法被称为evreytime,状态会发生变化(包括导航),但是正如我所看到的,您正在尝试在build方法中获取屏幕尺寸evreytime,因此我创建了这个库,该库可能对您有帮助{{3 }}。