如何防止在Flutter中的屏幕之间来回导航时重复调用API

5q4ezhmt  于 2022-12-05  发布在  Flutter
关注(0)|答案(1)|浏览(186)

我现在遇到的问题是,无论我做什么,特定的API都会被重复调用。我已经想到了几种方法来避免这种情况,但每次我在页面之间来回移动时,这种情况都会一再发生。我必须处理的数据类型是Map<String, dynamic>,我已经尝试过放置一个检查,您可以在下面的代码中找到它。这个检查的灵感来自于早期的一段代码,在这段代码中,我通过检查从API接收到的数据是否存在来防止重复的API调用。唯一的区别是,我必须检查的日期集是List<dynamic>类型,下面也有相应的代码。我想知道我可以做些什么来防止在页面上来回导航时重复调用API。
运行的代码提取(List<dynamic>

class CategoryProvider with ChangeNotifier {
  String baseUrl = 'http://*********';
  List<dynamic> _category = [];

  List<dynamic> get category {
    return [..._category];
  }

  List<dynamic> get categoriesList {
    return [..._categoriesList];
  }

  Future<void> getCategory() async {
    final url = Uri.parse(baseUrl + 'api/category-list/');
    print('Before Category API Call: $_category');
    if (_category.length < 1) {      //This here is a simple check which will basically detemine wether or not the API call needs to happen
      final response = await http.get(url);
      _category = json.decode(response.body);

      print('CATEGORY API CALLLLLLLLL');
    }

    print('Categoryssssssssssssss $_category');
  }
}

实现此功能的小部件:

class Categories extends StatefulWidget {
  CategoriesState createState() => CategoriesState();
}

class CategoriesState extends State<Categories> {
  bool isLoading = true;

  @override
  void initState() {
    // TODO: implement initState
    Provider.of<CategoryProvider>(context, listen: false)
        .getCategory()
        .then((_) {
      setState(() {
        isLoading = false;
      });
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final height = MediaQuery.of(context).size.height;
    final width = MediaQuery.of(context).size.width;
    final tabLayout = width > 600;
    final largeLayout = width > 350 && width < 600;
    final provider =
        Provider.of<CategoryProvider>(context, listen: false).category;
        
    return Padding(
      padding: EdgeInsets.only(left: width * 0.04, right: width * 0.04),
      child: Container(
        width: width * 0.9,
        height: !tabLayout && !largeLayout ? height * 0.28 : height * 0.25,
        decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(20),
            boxShadow: const [
              BoxShadow(color: Colors.grey, blurRadius: 5, offset: Offset(0, 2))
            ]),
        child: Column(
          children: [
            Padding(
              padding: EdgeInsets.only(
                  left: width * 0.04, top: height * 0.01, right: width * 0.04),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text(
                    'Categories',
                    // textScaleFactor: textScaleFactor,
                    style: TextStyle(
                        color: Colors.black,
                        fontWeight: FontWeight.bold,
                        fontSize: tabLayout
                            ? 25
                            : largeLayout
                                ? 17
                                : 12),
                  ),
                  InkWell(
                    onTap: () =>
                        Navigator.of(context).pushNamed('/category-screen'),
                    child: Text(
                      'View All',
                      // textScaleFactor: textScaleFactor,
                      style: TextStyle(
                          color: Colors.greenAccent,
                          fontSize: tabLayout
                              ? 18
                              : largeLayout
                                  ? 14
                                  : 10),
                    ),
                  )
                ],
              ),
            ),
            Expanded(
              child: isLoading
                  ? const Center(
                      child: CircularProgressIndicator(
                        color: Colors.green,
                      ),
                    )
                  : Container(
                      width: double.infinity,
                      height: height * 0.1,
                      margin: EdgeInsets.only(top: height * 0.01),
                      padding: EdgeInsets.only(
                          left: width * 0.02,
                          top: height * 0.005,
                          right: width * 0.02,
                          bottom: height * 0.008),
                      decoration: BoxDecoration(
                        // color: Colors.red,
                        borderRadius: BorderRadius.circular(20),
                      ),
                      child: ListView.builder(
                        scrollDirection: Axis.horizontal,
                        itemBuilder: (context, index) => Container(
                          width: width * 0.3,
                          height: height * 0.06,
                          // padding: EdgeInsets.fromLTRB(width * 0.02, height * 0.01,
                          //     width * 0.02, height * 0.01),
                          margin: EdgeInsets.only(right: width * 0.02),
                          padding: EdgeInsets.only(
                              left: width * 0.02, right: width * 0.02),
                          // color: Colors.green,
                          child: Column(
                            mainAxisAlignment: MainAxisAlignment.start,
                            children: [
                              Padding(
                                padding: EdgeInsets.only(top: height * 0.004),
                                child: InkWell(
                                  onTap: () => Navigator.of(context)
                                      .push(MaterialPageRoute(
                                    builder: (context) => CategoryList(
                                        provider[index]['id'],
                                        provider[index]['name']),
                                  )),
                                  child: Container(
                                    width: double.infinity,
                                    height: tabLayout
                                        ? height * 0.14
                                        : largeLayout
                                            ? height * 0.12
                                            : height * 0.15,
                                    decoration: BoxDecoration(
                                      color: Colors.green[100],
                                      borderRadius: BorderRadius.circular(20),
                                    ),
                                    child: Image.network(
                                        provider[index]['categoryImage']),
                                  ),
                                ),
                              ),
                              SizedBox(height: height * 0.01),
                              Text(
                                provider[index]['name'],
                                textAlign: TextAlign.center,
                                // textScaleFactor: textScaleFactor,
                                style: TextStyle(
                                    color: Colors.black,
                                    fontWeight: FontWeight.bold,
                                    fontSize: tabLayout
                                        ? width * 0.02
                                        : largeLayout
                                            ? 14
                                            : 12),
                              )
                            ],
                          ),
                        ),
                        itemCount: provider.length,
                      ),
                    ),
            )
          ],
        ),
      ),
    );
  }
}

针对类型Map<String, dynamic>进行检查的代码不起作用:

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

class PopularDealsProvider with ChangeNotifier {
  String baseUrl = 'http://**********';
  Map<String, dynamic> _popularDeals = {};

  Map<String, dynamic> get popularDeals {
    return {..._popularDeals};
  }

  Future<void> getPopularDeals() async {
    print('Before API Call: $_popularDeals');

    if (_popularDeals == {}) {        //This check was meant to make the call only if _popularDeals was a blank Map
    final url = Uri.parse(baseUrl + 'api/dashboard/popular/ordered-product/');

    final response = await http.get(url);

    var res = json.decode(response.body);

    _popularDeals = res;

    print('API Called');
    }

    print('PopularDeals $_popularDeals');
  }
}

实现此功能的小部件:

class PopularDeals extends StatefulWidget {
  PopularDealsState createState() => PopularDealsState();
}

class PopularDealsState extends State<PopularDeals> {
  bool isLoading = true;

  @override
  void initState() {
    // TODO: implement initState
    Provider.of<PopularDealsProvider>(context, listen: false)
        .getPopularDeals()
        .then((_) {
      setState(() {
        isLoading = false;
      });
    });
    itemDetail;
    super.initState();
  }

  void itemDetail(int categoryId) async {
    Provider.of<CategoryProductsProvider>(context, listen: false)
        .getCategoryProducts(categoryId);
  }

  @override
  Widget build(BuildContext context) {
    final height = MediaQuery.of(context).size.height;
    final width = MediaQuery.of(context).size.width;
    // final textScaleFactor = MediaQuery.of(context).textScaleFactor * 1.2;
    final tabLayout = width > 600;
    final largeLayout = width > 350 && width < 600;
    final provider = Provider.of<PopularDealsProvider>(context).popularDeals;
    final productsProvider =
        Provider.of<CategoryProductsProvider>(context).categoryProducts;

    // TODO: implement build
    return isLoading
        ? const Center(
            child: CircularProgressIndicator(
              color: Colors.green,
            ),
          )
        : Padding(
            padding: EdgeInsets.only(left: width * 0.04, right: width * 0.04),
            child: Container(
              width: width * 0.9,
              height: tabLayout
                  ? height * 0.35
                  : largeLayout
                      ? height * 0.34
                      : height * 0.35,
              margin: EdgeInsets.only(bottom: height * 0.04),
              decoration: BoxDecoration(
                  color: Colors.green[50],
                  borderRadius: BorderRadius.circular(20),
                  boxShadow: const [
                    BoxShadow(
                        color: Colors.grey, blurRadius: 5, offset: Offset(0, 2))
                  ]),
              child: Column(
                children: [
                  Padding(
                    padding: EdgeInsets.only(
                        left: width * 0.04,
                        top: height * 0.01,
                        right: width * 0.04),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Text(
                          'Popular Deals',
                          // // textScaleFactor: textScaleFactor,
                          style: TextStyle(
                              color: Colors.black,
                              fontWeight: FontWeight.bold,
                              fontSize: tabLayout
                                  ? 25
                                  : largeLayout
                                      ? 17
                                      : 12),
                        ),
                        Text(
                          'View All',
                          // // textScaleFactor: textScaleFactor,
                          style: TextStyle(
                              color: Colors.green,
                              fontWeight: FontWeight.bold,
                              fontSize: tabLayout
                                  ? 18
                                  : largeLayout
                                      ? 14
                                      : 10),
                        )
                      ],
                    ),
                  ),
                  Expanded(
                    child: Container(
                      width: double.infinity,
                      height: height * 0.1,
                      padding: EdgeInsets.fromLTRB(width * 0.02, height * 0.005,
                          width * 0.02, height * 0.008),
                      margin: EdgeInsets.only(top: height * 0.01),
                      decoration: const BoxDecoration(
                        // color: Colors.red,
                        borderRadius: BorderRadius.only(
                            bottomLeft: Radius.circular(20),
                            bottomRight: Radius.circular(20)),
                      ),
                      child: ListView.builder(
                        scrollDirection: Axis.horizontal,
                        itemBuilder: (context, index) => Container(
                          width: tabLayout ? width * 0.35 : width * 0.45,
                          height: double.infinity,
                          margin: EdgeInsets.only(right: width * 0.02),
                          padding: const EdgeInsets.all(5),
                          // color: Colors.amber,
                          child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                Container(
                                  decoration: BoxDecoration(
                                      color: Colors.white,
                                      borderRadius: BorderRadius.circular(30),
                                      boxShadow: const [
                                        BoxShadow(
                                            color: Colors.grey,
                                            blurRadius: 5,
                                            offset: Offset(1, 2))
                                      ]),
                                  child: InkWell(
                                    onTap: () => Navigator.of(context)
                                        .pushNamed('/item-details', arguments: {
                                      'id': provider['data'][index][0]['id'],
                                      'image': provider['data'][index][0]
                                          ['main_image'],
                                      'name': provider['data'][index][0]
                                          ['name'],
                                      'quantity': 0,
                                      'description': provider['data'][index][0]
                                          ['description'],
                                      'price': provider['data'][index][0]
                                          ['price']
                                    }),
                                    child: Image.network(
                                      'http://54.80.135.220${provider['data'][index][0]['main_image']}',
                                      fit: BoxFit.contain,
                                      width: tabLayout
                                          ? width * 0.35
                                          : largeLayout
                                              ? width * 0.45
                                              : width * 0.46,
                                      height: tabLayout
                                          ? height * 0.24
                                          : largeLayout
                                              ? height * 0.2
                                              : height * 0.22,
                                    ),
                                  ),
                                ),
                                SizedBox(height: height * 0.01),
                                Padding(
                                  padding: EdgeInsets.only(left: width * 0.03),
                                  child: Text(
                                    provider['data'][index][0]['name'],
                                    // // textScaleFactor: textScaleFactor,
                                    style: TextStyle(
                                        color: Colors.black,
                                        fontWeight: FontWeight.bold,
                                        fontSize: tabLayout
                                            ? width * 0.02
                                            : largeLayout
                                                ? 14
                                                : 12),
                                  ),
                                ),
                                Padding(
                                  padding: EdgeInsets.only(left: width * 0.03),
                                  child: Text(
                                      '₹${provider['data'][index][0]['price']}/${provider['data'][index][0]['uom']['short_name']}',
                                      // // textScaleFactor: textScaleFactor,
                                      style: TextStyle(
                                          color: Colors.black,
                                          fontWeight: FontWeight.bold,
                                          fontSize: tabLayout
                                              ? width * 0.02
                                              : largeLayout
                                                  ? 14
                                                  : 1)),
                                ),
                              ]),
                        ),
                        itemCount: provider['data'].length,   //The error gets thrown at this line
                      ),
                    ),
                  )
                ],
              ),
            ),
          );
  }
}

以下是错误消息:

The getter 'length' was called on null.
Receiver: null
Tried calling: length

有没有人可以帮忙??
另外,我已经用List<dynamic>类型的数据处理了这个问题。我只需要一种方法来处理Map<String, dynamic>类型的数据

相关问题