小部件库捕获异常,IDE 说 getter 在 null 上被调用,即使它不是 null

flutter Exception caught by widgets library, IDE says getter was called on null even it isn't null

我正在用 flutter 编写一个移动应用程序,我得到一个 json 并将其转换为一个对象,如下所示 class:

class UserProfile {   
 String role;   
 List<Town> interestingTown;   
 String sId;   
 String uid;   
 Town myTown;   
 int iV;

 UserProfile(
      {this.role,
        this.interestingTown,
        this.sId,
        this.uid,
        this.myTown,
        this.iV});

  UserProfile.fromJson(Map<String, dynamic> json) {
    role = json['role'];
    if (json['interestingTown'] != null) {
      interestingTown = new List<Town>();
      json['interestingTown'].forEach((v) {
        interestingTown.add(new Town.fromJson(v));
      });
    }
    sId = json['_id'];
    uid = json['uid'];
    myTown = json['myTown'] != null
        ? new Town.fromJson(json['myTown'])
        : null;
    iV = json['__v'];   
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['role'] = this.role;
    if (this.interestingTown != null) {
      data['interestingTown'] =
          this.interestingTown.map((v) => v.toJson()).toList();
    }
    data['_id'] = this.sId;
    data['uid'] = this.uid;
    if (this.myTown != null) {
      data['myTown'] = this.myTown.toJson();
    }
    data['__v'] = this.iV;
    return data;   
  }

  static Resource<myTown> get profile {
    return Resource(
        url: Constants.HEADLINE_GET_PROFILO,
        parse: (response) {
          UserProfile profile = UserProfile.fromJson(jsonDecode(response.body));
          return profile;
        });   
  }
}

class Town{   
  bool enabled;   
  List<String> categories;   
  String sId;   
  String nameTown;   
  int iV;

  Town(
      {this.enabled,
        this.categories,
        this.sId,
        this.nameTown,
        this.iV});

  Town.fromJson(Map<String, dynamic> json) {
    enabled = json['enabled'];
    categories = json['categories'].cast<String>();
    sId = json['_id'];
    nameTown = json['nameTown'];
    iV = json['__v'];   }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['enabled'] = this.enabled;
    data['categories'] = this.categories;
    data['_id'] = this.sId;
    data['nameTown'] = this.nameTown;
    data['__v'] = this.iV;
    return data;   }

}

之后,当我运行下面的class加载一个屏幕时,我得到这个错误(模拟器屏幕红了将近5秒):

======== Exception caught by widgets library =======================================================
The following NoSuchMethodError was thrown building MyAccountsPage(dirty, state: MyAccountsPageList#4dae7):
The getter 'myTown' was called on null.
Receiver: null
Tried calling: myTown

The relevant error-causing widget was: 
  MyAccountsPage file:///C:/Users/StudioProjects/my_project/lib/bloc.navigation_bloc/navigation_bloc.dart:36:15
When the exception was thrown, this was the stack: 
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
#1      MyAccountsPageList.build (package:civic_points/pages/myaccountspage.dart:145:35)
#2      StatefulElement.build (package:flutter/src/widgets/framework.dart:4612:27)
#3      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4495:15)
#4      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4667:11)
...
====================================================================================================

将近五秒钟后,屏幕加载但加载不正确,因为布尔变量设置不正确。 但是,问题是我可以打印 profile.myTown.nameTown,所以 myTown 不为空。

如果我尝试打印 profile.interestingTown[0].nameTown.

,也会发生同样的错误

之前,我曾尝试使用一些 if 语句设置变量,但我遇到了同样的错误,屏幕一直保持红色,几秒钟后没有加载。

我无法修复错误,所以我 post 了 class 的所有代码,希望有人能帮助我解决问题。

class MyAccountsPage extends StatefulWidget with NavigationStates {
  @override
  createState() => MyAccountsPageList();
}

class MyAccountsPageList extends State<MyAccountsPage> {

  UserProfile profile;
  bool boolinterestingTown = true;
  bool boolmyTown = true;
  int modify;
  int myIndex;
  bool add = false;
  var deleteTown;

  @override
  void initState() {
    super.initState();
    _getProfile();
    try {
      print (profile.myTown.nameTown);
    } catch (e) {
      boolmyTown = false;
      try {
        print(profile.interestingTown[0].nameTown);
      } catch (e) {
        boolinterestingTown = false;
      }
    }

    
  }

  void _getProfile() {
    WebserviceToken().load(UserProfile.profile).then((getProfile) => {
      setState(() => {this.profile = getProfile}),
    });
  }

  void deleteTownMe() async {
    var headers = {'Content-Type': 'application/json',
      'Authorization': 'Bearer ${token}'};
    var request = http.Request(
        'DELETE', Uri.parse('http:..........'));
    request.body = '''{
                  "town": "${deleteTown}"
                }''';
    request.headers.addAll(headers);

    http.StreamedResponse response = await request.send();

    if (response.statusCode == 201) {
      print(response.statusCode);
      print(await response.stream.bytesToString());
    } else {
      print(response.reasonPhrase);
    }
  }

  Widget _buildItemsForTownListView(BuildContext context, int index) {
    final town = profile.interestingTown[index].nameTown;
    return new Container(
      child: Column(
        children: <Widget>[
          Text(
            town,
            style: TextStyle(
                fontSize: 20,
                color: Colors.blueGrey,
                fontWeight: FontWeight.bold),
          ),
          ListTile(
            title: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Flexible(
                  child: RaisedButton(
                    child: Text("Modify"),
                    textColor: Colors.white,
                    color: Colors.blueGrey,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(8.0),
                    ),
                    onPressed: () {
                      modify = 2;
                      myIndex = index;
                      Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (context) => citySelection(
                                profileParameters:
                                new ProfileParameters(modify, myIndex, add, town),
                              )));
                    },
                  ),
                ),
                SizedBox(width: 10),
                Flexible(
                  child: RaisedButton(
                    child: Text("Delete"),
                    textColor: Colors.white,
                    color: Colors.blueGrey,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(8.0),
                    ),
                    onPressed: () {
                      deleteTown = town;
                      deleteTownMe();
                      Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (context) => citySelection()));
                    },
                  ),
                ),
              ],
            ),
          ),
          SizedBox(height: 20),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    var myTown = profile.myTown.nameTown;
    print(profile.myTown.nameTown);
    return Scaffold(
      appBar: AppBar(
        titleSpacing: 50.0,
        title: new Text("My profile"),
        automaticallyImplyLeading: false,
      ),
      body: SingleChildScrollView(
        child: Container(
          margin: const EdgeInsets.fromLTRB(16, 16, 0, 0),
          width: double.infinity,
          color: Colors.white,
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              mainAxisSize: MainAxisSize.max,
              children: <Widget>[
                SizedBox(height: 40),
                CircleAvatar(
                  backgroundImage: NetworkImage(
                    imageUrl,
                  ),
                  radius: 48,
                  backgroundColor: Colors.transparent,
                ),
                SizedBox(height: 48),
                Text(
                  'User',
                  style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
                ),
                Text(
                  name,
                  style: TextStyle(
                      fontSize: 20,
                      color: Colors.blueGrey,
                      fontWeight: FontWeight.bold),
                ),
                SizedBox(height: 20),
                if (boolmyTown)
                  Text(
                    'My town',
                    style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
                  ),
                if (boolmyTown)
                  Text(
                    myTown,
                    style: TextStyle(
                        fontSize: 20,
                        color: Colors.blueGrey,
                        fontWeight: FontWeight.bold),
                  ),
                if (boolmyTown)
                  RaisedButton(
                    child: Text("Modify"),
                    textColor: Colors.white,
                    color: Colors.blueGrey,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(8.0),
                    ),
                    onPressed: () {
                      modify = 1;
                      myIndex = 0;
                      Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (context) => citySelection(
                                profileParameters:
                                new ProfileParameters(modify, myIndex, add, ''),
                              )));
                    },
                  ),
                if (boolinterestingTown && boolmyTown)
                  SizedBox(height: 20),
                if (boolinterestingTown && boolmyTown)
                  Text(
                    'Interesting towns',
                    style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
                  ),
                if (boolinterestingTown && boolmyTown)
                  ListView.builder(
                    itemCount: profile.interestingTowns.length,
                    shrinkWrap: true,
                    itemBuilder: _buildItemsForTownListView,
                  ),
                if (boolmyTown && !boolinterestingTown)
                  SizedBox(height: 20),
                if (boolmyTown)
                  RaisedButton(
                    child: Text("Add ineresting town"),
                    textColor: Colors.white,
                    color: Colors.blueGrey,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(8.0),
                    ),
                    onPressed: () {
                      modify = 2;
                      myIndex = profile.interestingTown.length;
                      add = true;
                      Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (context) => citySelection(
                                profileParameters:
                                new ProfileParameters(modify, myIndex, add, ''),
                              )));
                    },
                  ),
                if (!boolmyTown)
                  RaisedButton(
                    child: Text("Add your town"),
                    textColor: Colors.white,
                    color: Colors.blueGrey,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(8.0),
                    ),
                    onPressed: () {
                      modify = 1;
                      myIndex = 0;
                      Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (context) => citySelection(
                                profileParameters:
                                new ProfileParameters(modify, myIndex, add, ''),
                              )));
                    },
                  ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

您需要确认变量 profile 是否为空。

@override
void initState() {
   super.initState();
   
   WidgetsBinding.instance.addPostFrameCallback((_) {
       _getProfile();
   });    
}

@override
Widget build(BuildContext context) {
    var myTown = (profile == null) ? null : profile.myTown.nameTown;
    
    return Scaffold(
      appBar: AppBar(
        titleSpacing: 50.0,
        title: new Text("My profile"),
        automaticallyImplyLeading: false,
      ),
      body: (profile == null) 
         ? Center(child: CircularProgressIndicator(),)
         : SingleChildScrollView(child: Container(),),
    );
}