首页 > 解决方案 > Flutter Navigator.pop 再次运行小部件构建方法

问题描述

我有两个小部件

  1. 类别小部件 - 我在其中显示类别的名称和图像
  2. CategoryDe​​tailsS​​creen 小部件 - 我在其中显示与该类别相关的项目列表

我在类别小部件上有onTap方法,从中我将一些路由参数传递到详细信息屏幕

onTap: () {
    Navigator.of(context).pushNamed(
      CategoryDetailScreen.routeName,
      arguments: {
        'id': id,
        'name': name,
        'slug': slug,
      },
    );
  }

在类别详细信息页面上,我得到了这些论点

final categoryArgs =
    ModalRoute.of(context).settings.arguments as Map<String, String>;

现在,当我尝试使用应用栏后退按钮返回时,它再次调用我的类别详细信息屏幕的构建方法。然后它再次调用我的 API。我想避免这种情况,并且不想在返回类别页面时再次调用我的 API。

这是我的两个小部件的完整代码 -

类别.dart

import 'package:flutter/material.dart';
import 'dart:ui';
import 'package:cached_network_image/cached_network_image.dart';

import 'package:captionsocial/screens/category_detail_screen.dart';

class Category extends StatelessWidget {
  final String id;
  final String name;
  final String image;
  final String slug;

  Category(this.id, this.name, this.image, this.slug);

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () {
        Navigator.of(context).pushNamed(
          CategoryDetailScreen.routeName,
          arguments: {
            'id': id,
            'name': name,
            'slug': slug,
          },
        );
      },
      borderRadius: BorderRadius.circular(12),
      child: Container(
        decoration: BoxDecoration(
          image: DecorationImage(
            alignment: Alignment.center,
            fit: BoxFit.cover,
            image: CachedNetworkImageProvider(
              image,
            ),
          ),
          borderRadius: BorderRadius.circular(12),
        ),
        child: ClipRRect(
          borderRadius: BorderRadius.circular(12),
          child: BackdropFilter(
            filter: ImageFilter.blur(sigmaX: 0, sigmaY: 0),
            child: Container(
              alignment: Alignment.center,
              color: Colors.black.withOpacity(0.5),
              child: Text(
                name,
                textAlign: TextAlign.center,
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 20,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

类别详细信息屏幕

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../providers/posts.dart';

class CategoryDetailScreen extends StatelessWidget {
  static const routeName = 'category-detail';

  @override
  Widget build(BuildContext context) {
    print('running again');
    final categoryArgs =
        ModalRoute.of(context).settings.arguments as Map<String, String>;
    final productsData = Provider.of<Posts>(context, listen: false);
    final temp = productsData.getPostsBySlug(categoryArgs['slug']);

    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        leading: IconButton(
            icon: Icon(Icons.arrow_back_ios),
            onPressed: () {
              Navigator.pop(context);
            }),
        elevation: 1,
        backgroundColor: Colors.white,
        title: Text(
          categoryArgs['name'],
          style: TextStyle(color: Theme.of(context).primaryColor),
        ),
      ),
      body: FutureBuilder(
        future: temp,
        builder: (ctx, snapShot) =>
            snapShot.connectionState == ConnectionState.waiting
                ? Center(
                    child: CircularProgressIndicator(),
                  )
                : Consumer<Posts>(
                    builder: (ct, postsData, child) => Padding(
                      padding: EdgeInsets.symmetric(horizontal: 0, vertical: 0),
                      child: ListView.builder(
                        padding: const EdgeInsets.all(10.0),
                        itemCount: postsData.posts.length,
                        itemBuilder: (ctx, i) => Text(postsData.posts[i].title),
                      ),
                    ),
                  ),
      ),
    );
  }
}

导致问题的行是

final categoryArgs =
    ModalRoute.of(context).settings.arguments as Map<String, String>;

如果我删除上面的行,那么当我使用 appbar 后退按钮返回时,不会再次调用 build 方法。

标签: flutterdart

解决方案


你需要在StatefulWidget这里使用。据我所知,你无法控制颤振何时调用build小部件的方法,即使是无状态的也是如此。

将涉及您的部分移至Future您的. 由于需要 ,因此可能无法用于这种情况,因此如果这导致错误,请将其移至。initStateStateStatefulWidgetinitStateBuildContextdidChangeDependencies

class CategoryDetailScreen extends StatefulWidget {
  @override
  _CategoryDetailScreenState createState() => _CategoryDetailScreenState();
}

class _CategoryDetailScreenState extends State<CategoryDetailScreen> {
  var temp;

  @override
  void initState() {
    super.initState();
    final categoryArgs =
        ModalRoute.of(context).settings.arguments as Map<String, String>;
    final productsData = Provider.of<Posts>(context, listen: false);
    temp = productsData.getPostsBySlug(categoryArgs['slug']);
  }

推荐阅读