dart (Flutter)如何将数据从当前页面传递到上一页?如何根据条件将其显示在ListTile上?

blmhpbnm  于 2023-04-27  发布在  Flutter
关注(0)|答案(2)|浏览(109)

你好,我是新的Flutter,我想做一个功能,当我按下“添加到购物车按钮”,我想从当前页面传递数据(例如:PsuListPage)并显示在ListTile上,并根据WishListPage上的id product将title的默认值替换为product的数据。怎么做?
ApiPsu

import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:http/http.dart' as http;

import '/model/psu_model.dart';

class ApiPsu {
  static const String url = 'http://192.168.251.119:3000/psu';

  static Future<List<PsuModel>> getPsu() async {
    final response = await Dio().get(url);
    print('response: $response');
    if (response.statusCode == 200) {
      final List<dynamic> data = response.data;
      final List<PsuModel> psu =
          data.map<PsuModel>((json) => PsuModel.fromJson(json)).toList();
      return psu;
    } else {
      throw Exception('Failed to load data');
    }
  }
}

PsuModel
注:我只使用标题产品,id,图像,价格,评级

import 'dart:convert';

List<PsuModel> psuModelFromJson(String str) =>
    List<PsuModel>.from(json.decode(str).map((x) => PsuModel.fromJson(x)));

String psuModelToJson(List<PsuModel> data) =>
    json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class PsuModel {
  PsuModel({
    required this.id,
    required this.title,
    required this.asin,
    required this.link,
    required this.categories,
    required this.image,
    this.amazonsChoice,
    this.isPrime,
    required this.rating,
    required this.ratingsTotal,
    required this.price,
    this.bestseller,
    this.isSmallBusiness,
    this.isCarousel,
    this.carousel,
    this.availability,
    this.coupon,
  });

  int id;
  String title;
  String asin;
  String link;
  List<Category> categories;
  String image;
  AmazonsChoice? amazonsChoice;
  bool? isPrime;
  double? rating;
  int? ratingsTotal;
  Price price;
  Bestseller? bestseller;
  bool? isSmallBusiness;
  bool? isCarousel;
  Carousel? carousel;
  Availability? availability;
  Coupon? coupon;

  factory PsuModel.fromJson(Map<String, dynamic> json) => PsuModel(
        id: json["id"],
        title: json["title"],
        asin: json["asin"],
        link: json["link"],
        categories: List<Category>.from(
            json["categories"].map((x) => Category.fromJson(x))),
        image: json["image"],
        amazonsChoice: json["amazons_choice"] == null
            ? null
            : AmazonsChoice.fromJson(json["amazons_choice"]),
        isPrime: json["is_prime"],
        rating: json["rating"]?.toDouble(),
        ratingsTotal: json["ratings_total"],
        price: Price.fromJson(json["price"]),
        bestseller: json["bestseller"] == null
            ? null
            : Bestseller.fromJson(json["bestseller"]),
        isSmallBusiness: json["is_small_business"],
        isCarousel: json["is_carousel"],
        carousel: json["carousel"] == null
            ? null
            : Carousel.fromJson(json["carousel"]),
        availability: json["availability"] == null
            ? null
            : Availability.fromJson(json["availability"]),
        coupon: json["coupon"] == null ? null : Coupon.fromJson(json["coupon"]),
      );

  Map<String, dynamic> toJson() => {
        "id": id,
        "title": title,
        "asin": asin,
        "link": link,
        "categories": List<dynamic>.from(categories.map((x) => x.toJson())),
        "image": image,
        "amazons_choice": amazonsChoice?.toJson(),
        "is_prime": isPrime,
        "rating": rating,
        "ratings_total": ratingsTotal,
        "price": price.toJson(),
        "bestseller": bestseller?.toJson(),
        "is_small_business": isSmallBusiness,
        "is_carousel": isCarousel,
        "carousel": carousel?.toJson(),
        "availability": availability?.toJson(),
        "coupon": coupon?.toJson(),
      };
}

class AmazonsChoice {
  AmazonsChoice({
    required this.link,
    required this.keywords,
  });

  String link;
  String keywords;

  factory AmazonsChoice.fromJson(Map<String, dynamic> json) => AmazonsChoice(
        link: json["link"],
        keywords: json["keywords"],
      );

  Map<String, dynamic> toJson() => {
        "link": link,
        "keywords": keywords,
      };
}

class Availability {
  Availability({
    required this.raw,
  });

  String raw;

  factory Availability.fromJson(Map<String, dynamic> json) => Availability(
        raw: json["raw"],
      );

  Map<String, dynamic> toJson() => {
        "raw": raw,
      };
}

class Bestseller {
  Bestseller({
    required this.link,
    required this.category,
  });

  String link;
  String category;

  factory Bestseller.fromJson(Map<String, dynamic> json) => Bestseller(
        link: json["link"],
        category: json["category"],
      );

  Map<String, dynamic> toJson() => {
        "link": link,
        "category": category,
      };
}

class Carousel {
  Carousel({
    required this.title,
    required this.subTitle,
    required this.id,
  });

  String title;
  String subTitle;
  String id;

  factory Carousel.fromJson(Map<String, dynamic> json) => Carousel(
        title: json["title"],
        subTitle: json["sub_title"],
        id: json["id"],
      );

  Map<String, dynamic> toJson() => {
        "title": title,
        "sub_title": subTitle,
        "id": id,
      };
}

class Category {
  Category({
    required this.name,
    required this.id,
  });

  Name name;
  Id id;

  factory Category.fromJson(Map<String, dynamic> json) => Category(
        name: nameValues.map[json["name"]] ?? Name.ALL_DEPARTMENTS,
        id: idValues.map[json["id"]] ?? Id.APS,
      );

  Map<String, dynamic> toJson() => {
        "name": nameValues.reverse[name],
        "id": idValues.reverse[id],
      };
}

enum Id { APS }

final idValues = EnumValues({"aps": Id.APS});

enum Name { ALL_DEPARTMENTS }

final nameValues = EnumValues({"All Departments": Name.ALL_DEPARTMENTS});

class Coupon {
  Coupon({
    required this.badgeText,
    required this.text,
  });

  String badgeText;
  String text;

  factory Coupon.fromJson(Map<String, dynamic> json) => Coupon(
        badgeText: json["badge_text"],
        text: json["text"],
      );

  Map<String, dynamic> toJson() => {
        "badge_text": badgeText,
        "text": text,
      };
}

class Price {
  Price({
    this.symbol,
    this.value,
    this.currency,
    required this.raw,
    this.name,
    this.isPrimary,
    this.asin,
    this.link,
  });

  Symbol? symbol;
  double? value;
  Currency? currency;
  String raw;
  String? name;
  bool? isPrimary;
  String? asin;
  String? link;

  factory Price.fromJson(Map<String, dynamic> json) => Price(
        symbol: symbolValues.map[json["symbol"]] ?? Symbol.EMPTY,
        value: json["value"]?.toDouble(),
        currency: currencyValues.map[json["currency"]] ?? Currency.USD,
        raw: json["raw"],
        name: json["name"],
        isPrimary: json["is_primary"],
        asin: json["asin"],
        link: json["link"],
      );

  Map<String, dynamic> toJson() => {
        "symbol": symbolValues.reverse[symbol],
        "value": value,
        "currency": currencyValues.reverse[currency],
        "raw": raw,
        "name": name,
        "is_primary": isPrimary,
        "asin": asin,
        "link": link,
      };
}

enum Currency { USD }

final currencyValues = EnumValues({"USD": Currency.USD});

enum Symbol { EMPTY }

final symbolValues = EnumValues({"\u0024": Symbol.EMPTY});

class EnumValues<T> {
  Map<String, T> map;
  late Map<T, String> reverseMap;

  EnumValues(this.map);

  Map<T, String> get reverse {
    reverseMap = map.map((k, v) => MapEntry(v, k));
    return reverseMap;
  }
}

PsuProvider

import 'package:flutter/material.dart';

import '../api/psu_api.dart';
import '../model/psu_model.dart';

enum RequestState { empty, loading, loaded, error }

class PsuProvider extends ChangeNotifier {
  RequestState _state = RequestState.empty;
  RequestState get state => _state;

  List<PsuModel> _psu = [];
  List<PsuModel> get psu => _psu;

  String _message = '';
  String get message => _message;

  Future<void> fetchPsu() async {
    _state = RequestState.loading;
    notifyListeners();
    try {
      final result = await ApiPsu.getPsu();
      _psu = result;
      _state = RequestState.loaded;

      notifyListeners();
    } catch (e) {
      _state = RequestState.error;
      _message = e.toString();
      notifyListeners();
    }
  }
}

PsuListPage

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

class PsuListPage extends StatefulWidget {
  const PsuListPage({super.key});

  @override
  State<PsuListPage> createState() => _PsuListPageState();
}

class _PsuListPageState extends State<PsuListPage> {
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    Future.microtask(
        () => Provider.of<PsuProvider>(context, listen: false).fetchPsu());
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('MandorPC'),
      ),
      body: Consumer<PsuProvider>(builder: (context, psu, child) {
        if (psu.state == RequestState.loading) {
          return const Center(
            child: CircularProgressIndicator(),
          );
        } else if (psu.state == RequestState.loaded) {
          return ListView.builder(
              itemCount: psu.psu.length,
              itemBuilder: (context, index) {
                return Card(
                    shape: const RoundedRectangleBorder(
                        side: BorderSide(color: Colors.blue),
                        borderRadius: BorderRadius.all(Radius.circular(10))),
                    child: InkWell(
                      onTap: () {},
                      child: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          Padding(
                            padding: const EdgeInsets.all(16),
                            child: Column(
                              children: [
                                Text(
                                  psu.psu[index].title,
                                  textAlign: TextAlign.justify,
                                ),
                                Image.network(psu.psu[index].image),
                                Text(
                                    'Rating : ${psu.psu[index].rating ?? 'No rating yet'}'),
                                Text(
                                    'Total Rating : ${psu.psu[index].ratingsTotal ?? 'No rating yet'}'),
                                Text('USD ${psu.psu[index].price.value}'),
                              ],
                            ),
                          ),
                          ElevatedButton(
                              onPressed: () {
                                Navigator.pop(context, psu.psu[index].id);
                              },
                              child: const Text('Add to Cart'))
                        ],
                      ),
                    ));
              });
        } else if (psu.state == RequestState.error) {
          return Center(
            child: Text(psu.message),
          );
        } else {
          return const Center(
            child: Text('Silakan klik tombol add untuk memulai'),
          );
        }
      }),
    );
  }
}

WishListPage

import 'package:flutter/material.dart';
import 'package:mini_project_mandor_pc/view/case_list_page.dart';
import 'package:mini_project_mandor_pc/view/cpu_cooler_page.dart';
import 'package:mini_project_mandor_pc/view/gpu_list_page.dart';
import 'package:mini_project_mandor_pc/view/motherboard_list_page.dart';
import 'package:mini_project_mandor_pc/view/psu_list_page.dart';
import 'package:mini_project_mandor_pc/view/ram_list_page.dart';
import 'package:mini_project_mandor_pc/view/storage_list_page.dart';
import 'package:mini_project_mandor_pc/view_model/gpu_provider.dart';
import 'package:mini_project_mandor_pc/view_model/psu_provider.dart';
import 'package:mini_project_mandor_pc/view_model/ram_provider.dart';
import 'package:mini_project_mandor_pc/view_model/storage_provider.dart';
import 'package:provider/provider.dart';

import '../view_model/case_provider.dart';
import '../view_model/cpu_cooler_provider.dart';
import '../view_model/cpu_provider.dart';
import '../view_model/motherboard_provider.dart';
import 'cpu_list_page.dart';

class WishListPage extends StatefulWidget {
  const WishListPage({super.key});

  @override
  State<WishListPage> createState() => _WishListPageState();
}

class _WishListPageState extends State<WishListPage> {
  List<String> _list = [
    'CPU',
    'GPU',
    'Motherboard',
    'RAM',
    'Storage',
    'PSU',
    'Case',
    'CPU Cooler'
  ];

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    Future.microtask(
        () => Provider.of<GpuProvider>(context, listen: false).fetchGpu());
    Future.microtask(
        () => Provider.of<MoboProvider>(context, listen: false).fetchMobo());
    Future.microtask(
        () => Provider.of<PsuProvider>(context, listen: false).fetchPsu());
    Future.microtask(
        () => Provider.of<RamProvider>(context, listen: false).fetchRam());
    Future.microtask(() =>
        Provider.of<StorageProvider>(context, listen: false).fetchStorage());
    Future.microtask(
        () => Provider.of<CpuProvider>(context, listen: false).fetchCpu());
    Future.microtask(() =>
        Provider.of<CpuCoolerProvider>(context, listen: false).fetchCooler());
    Future.microtask(
        () => Provider.of<CaseProvider>(context, listen: false).fetchCasing());
  }

  @override
  Widget build(BuildContext context) {
    final psuId = ModalRoute.of(context)?.settings.arguments as String;
    final psu = Provider.of<PsuProvider>(context, listen: false)
        .psu
        .firstWhere((element) => element.id == psuId);

    return Scaffold(
        appBar: AppBar(
          title: const Text('MandorPC'),
        ),
        body: ListView.builder(
            itemCount: 8,
            itemBuilder: (context, index) {
              return Card(
                child: InkWell(
                  onTap: () {
                    Navigator.push(context,
                        MaterialPageRoute(builder: (context) {
                      switch (index) {
                        case 1:
                          return const GpuListPage();
                        case 2:
                          return const MoboListPage();
                        case 3:
                          return const RamListPage();
                        case 4:
                          return const StorageListPage();
                        case 5:
                          return const PsuListPage();
                        case 6:
                          return const CaseListPage();
                        case 7:
                          return const CpuCoolerListPage();
                        default:
                          return const CpuListPage();
                      }
                    }));
                  },
                  child: ListTile(
                    title: Text('Masukkan ${_list[index]}'),
                  ),
                ),
              );
            }));
  }
}

我尝试了navigator.pop(context,psu.psu [index].id)
但我不知道接下来我该怎么做

inn6fuwd

inn6fuwd1#

我想你可以在navigator.pop当前页面后使用回调函数,这里有一些例子,我有第一页,所以这个页面将从第二页获取数据,

let's assume we are in the second page now, so create callback at second page contractor. 

1. first declare the callback
typedef DataCallback = void Function(String data);

class SecondPage extends StatelessWidget {
  final DataCallback dataCallback;

  SecondPage({Key? key, required this.dataCallback}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Second Page'),
      ),
      body: Center(
        child: ElevatedButton(
          child: Text('Send Data Back'),
          onPressed: () {
            2.// Call the callback function and pass in the data you want to send back to first page
            dataCallback('Hello from second page!');
            Navigator.pop(context);
          },
        ),
      ),
    );
  }
}

3. here: the first page this page should receive the data after the second page pop because the callback get called and bring the data as parameter

class FirstPage extends StatefulWidget {
  @override
  _FirstPageState createState() => _FirstPageState();
}

class _FirstPageState extends State<FirstPage> {
  String? _data;

  void _getDataFromSecondPage(String data) {
    setState(() {
   4. you can override the previous data using current new data from second page here.
      _data = data;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(_data ?? 'No data'),
            ElevatedButton(
              child: Text('Go to Second Page'),
              onPressed: () async {
                // Navigate to the second page and pass in the callback function
                await Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => SecondPage(
                      dataCallback: _getDataFromSecondPage,
                    ),
                  ),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}
ego6inou

ego6inou2#

为了做到这一点,你可以使用弹出的能力,如果你仔细看看它的实现,你会发现你可以传递可选的定位参数。

/// where you want navigate and get data back
onPress:()async{
  final result=await Navigator.of(context).push('/product');
}

那么你可以这样做

onPress:(){
// you could pass any object
 Navigator.of(context).pop('test data');
}

相关问题