继承小部件传递的参数不保留值

时间:2019-10-09 19:30:54

标签: flutter

我遇到的情况是我有我的主类和一个继承小部件。当我将主类包装在继承类中并传递一个参数时,由于某种原因,继承类未保留我传递的参数的值。下面是我的代码

主班

import 'package:flutter/material.dart';
import 'package:finsec/widget/drawer_widget.dart';
import 'package:finsec/widget/inherited_month_year.dart';
import 'package:finsec/screens/income/second_fragment.dart';
import 'package:finsec/screens/home/home_screen.dart';
import 'package:finsec/screens/transaction/transaction_list.dart';
import 'package:finsec/utils/colors.dart';
import 'package:finsec/utils/strings.dart';
import 'package:month_picker_dialog/month_picker_dialog.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:finsec/utils/localizations.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:finsec/model/month_year.dart';

void main() => runApp(new MyApp( initialDate: DateTime.now()));

class MyApp extends StatefulWidget {
  final String title = home;
  final DateTime initialDate;

  const MyApp({Key key, @required this.initialDate}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  DateTime selectedDate, prevSelectedDate;
  String monthName1;
  int monthNumber, year;
  MonthYear monthYear;

  getDrawerItemWidget(int pos, String title) {
    switch (pos) {
      case 0:
        return new HomeScreen ();
      case 1:
        return new SecondFragment();
      case 2:
        return new TransactionList(
          outstanding: totalOutstanding,
          received_or_paid:
          totalReceived, transactionType: title,);
      case 3:
        return new TransactionList(
          outstanding: totalOutstanding,
          received_or_paid: totalPaid,
          transactionType: title,);
      default:
        return new Text("Error");
    }
  }

  String titleAppBar = home;
  int tabIndex = 0;
  double elevation = 0;

  @override
  void initState() {
    setState(() {
      titleAppBar = widget.title;
    });
    super.initState();
    selectedDate = widget.initialDate;
  }


  void getMonthYear() {
    if(selectedDate != null) {
      monthName1 = monthNamesAbbrv[selectedDate.month];
      monthNumber = selectedDate.month;
      year = selectedDate.year;
      prevSelectedDate = selectedDate;
    }
    else {
      monthName1 = monthNamesAbbrv[prevSelectedDate.month];
      monthNumber = prevSelectedDate.month;
      year = prevSelectedDate.year;
    }

    monthYear = new MonthYear(monthNumber: monthNumber, year: year) ;
  }

  Widget homeScreen(BuildContext context) {


    return Scaffold(
      appBar: AppBar(
        title: Text(titleAppBar),
        elevation: elevation,
        backgroundColor: colorPrimary,
        actions: <Widget>[
          Builder(
           builder: (context) => FlatButton.icon(
            icon: Icon(Icons.calendar_today, color: white,), //`Icon` to display
            label: Text(monthName1 + ' $year'  , style: TextStyle(color: white, fontSize: 18)), //`Text` to display
            onPressed: () {
             // DateTime date = new DateTime.now();
             // showMonthPicker(context: context, initialDate: date);
              showMonthPicker(
                  context: context,
                  firstDate: DateTime( DateTime.now().year - 1 , 5),
                  lastDate: DateTime( DateTime.now().year + 1, 9 ),
                  initialDate: selectedDate ?? widget.initialDate
              )
                  .then((date) => setState(() {
                selectedDate = date ;//!= null ? date : prevSelectedDate;

              }));
            },
          ),
      )
        ],
      ),
      drawer: DrawerWidget((title, index) {
        setState(() {
          titleAppBar = title;
          tabIndex = index;
        });
      }, tabIndex),
      body: getDrawerItemWidget(tabIndex, titleAppBar),
    );
  }


  @override
  Widget build(BuildContext context) {
    getMonthYear();


    print('MONTH');
    print(monthYear.monthNumber);
    print('YEAR');
    print(monthYear.year);
    return StateContainer(
       // monthNumber: monthNumber,
       // year: year,
        child: new MaterialApp(
          localizationsDelegates: [
            GlobalMaterialLocalizations.delegate,
           GlobalWidgetsLocalizations.delegate,
          ],
          supportedLocales: [
            Locale('en'),
            Locale('zh'),
            Locale('fr'),
            Locale('es'),
            Locale('de'),
            Locale('ru'),
            Locale('ja'),
            Locale('ar'),
            Locale('fa'),
          ],
          title: widget.title,
          home: homeScreen(context)
       ),
      monthYear: monthYear,
    );
  }
}

继承小部件类

import 'package:flutter/material.dart';
import 'package:finsec/model/month_year.dart';

class StateContainer extends StatefulWidget {
  final Widget child;
  final MonthYear monthYear;

  StateContainer({@required this.child, this.monthYear});

  static StateContainerState of(BuildContext context) {
    return (context.inheritFromWidgetOfExactType(InheritedMonthYear)
    as InheritedMonthYear).data;
  }

  @override
  StateContainerState createState() => new StateContainerState();
}

class StateContainerState extends State<StateContainer> {
  MonthYear monthYear;// =new MonthYear(monthNumber: 4, year: 2012);

  void updateMonthYear({month, year}) {
    if (monthYear == null) {
      monthYear = new MonthYear(monthNumber: month, year: year);
      setState(() {
        monthYear = monthYear;
      });
    } else {
      setState(() {
        monthYear.monthNumber = month ?? monthYear.monthNumber;
        monthYear.year = year ?? monthYear.year;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    print('MONTH CONTAINER');
    print(monthYear.monthNumber);
    return InheritedMonthYear(
      data: this,
      child: widget.child,
    );
  }
}

class InheritedMonthYear extends InheritedWidget {
  final StateContainerState data;

  InheritedMonthYear({
    Key key,
    @required this.data,
    @required Widget child,
  }) :  super(key: key, child: child);


  static InheritedMonthYear of(BuildContext context) {
    return context.inheritFromWidgetOfExactType(InheritedMonthYear) as InheritedMonthYear;
  }


  @override
  bool updateShouldNotify(InheritedWidget oldWidget) => true;
 // bool updateShouldNotify(InheritedMonthYear old) {
   //return monthNumber != old.monthNumber || year != old.year;
 // }
}

在主类中,我在构建函数中调用getMonthYear()函数,该函数显示以下内容

I/flutter (23720): MONTH
I/flutter (23720): 10
I/flutter (23720): YEAR
I/flutter (23720): 2019

这些值存储在变量monthYear中,该变量从主类传递给StateContainer类。如果您在StateContainer类中注意到,则在生成函数im中打印我从main传递的值

  @override
  Widget build(BuildContext context) {
    print('MONTH CONTAINER');
    print(monthYear.monthNumber);
    return InheritedMonthYear(
      data: this,
      child: widget.child,
    );
  }

但是,我收到错误消息

I/flutter (23720): MONTH CONTAINER
I/flutter (23720): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (23720): The following NoSuchMethodError was thrown building StateContainer(dirty, state:
I/flutter (23720): StateContainerState#e2af1):
I/flutter (23720): The getter 'monthNumber' was called on null.
I/flutter (23720): Receiver: null
I/flutter (23720): Tried calling: monthNumber
I/flutter (23720): 
I/flutter (23720): User-created ancestor of the error-causing widget was:
I/flutter (23720):   MyApp file:///C:/Users/rodrigue33/Documents/APP/finsec/lib/main.dart:15:27
I/flutter (23720): 
I/flutter (23720): When the exception was thrown, this was the stack:
I/flutter (23720): #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:50:5)
I/flutter (23720): #1      StateContainerState.build (package:finsec/widget/inherited_month_year.dart:39:21)

当我尝试打印print(monthYear.monthNumber);看起来monthYear为空,并且抖动抛出错误。我不知道如果我从主类传递monthYear,并且在调用StateContainer类以验证monthYear不为null之前打印出这些值,怎么可能为null。有人可以告诉我我做错了什么吗?为什么当我将值(monthYear)传递给StateContainer时,值不保留,而是在StateContainer中使用monthYear为null?预先感谢

0 个答案:

没有答案