Flutter Navigator.pop再次运行小部件构建方法

时间:2020-09-11 13:55:44

标签: flutter dart

我有两个小部件

  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。

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

category.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后退按钮返回时,构建方法不会再次被调用。

1 个答案:

答案 0 :(得分:1)

您需要在此处使用StatefulWidget。据我所知,您无法控制flutter何时调用小部件的build方法,即使对于无状态的小部件也是如此。

将涉及Future的部分移至initState的{​​{1}}中的State。由于需要StatefulWidgetinitState可能不适用于这种情况,因此,如果导致错误,请将其移至BuildContext

didChangeDependencies