如果列表不为空,则颤振上下文变为空

时间:2021-01-04 05:59:08

标签: flutter dart nullpointerexception null flutter-provider

我有一个用于创建/更新活动的表单,它是一个像这样的有状态小部件:


class ActivityForm extends StatefulWidget {
  final Activity activity;
  final bool isEdit;

  const ActivityForm({Key key, this.activity, this.isEdit}) : super(key: key);

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

class _ActivityFormState extends State<ActivityForm> {
  final _formKey = GlobalKey<FormState>();
  List<int> activityDetailIdToBeDeleted;

  ...
  void submitHandler() async {
    setState(() {
      _isLoading = true;
    });

    // Mapping input field to activity model
    Activity activity = Activity(
        id: widget.activity.id,
        tanggal: _tanggalController.text,
        uraianKegiatan: _uraianKegiatanController.text,
        pic: _picController.text,
        jumlahTim: int.parse(_jumlahTimController.text),
        kendala: _kendalaController.text,
        penyelesaian: _penyelesaianController.text,
        approverUserId: selectedApprovalUser,
        rincianPekerjaan: rincianPekerjaanList,
        status: 'PENDING');

    if (widget.isEdit) {
      await Provider.of<ActivityProvider>(context, listen: false)
          .updateActivity(activity, activityDetailIdToBeDeleted);
    } else {
      await Provider.of<ActivityProvider>(context, listen: false)
          .createActivity(activity);
    }

    Navigator.pop(context);
  }

在我的表单中有一些活动的详细列表。当我按删除时,它会添加 “待删除”列表中的活动详情:

IconButton(
  icon: Icon(Icons.delete),
  onPressed: () => removeRincianPekerjaan(
  activityDetail.description),),

功能如下:

void removeRincianPekerjaan(desc) {
    if (widget.isEdit) {
      int detailId = rincianPekerjaanList
          .where((element) => element.description == desc)
          .first
          .id;
      if (!activityDetailIdToBeDeleted.contains(detailId))
        activityDetailIdToBeDeleted.add(detailId);
      print(activityDetailIdToBeDeleted);
    }

    setState(() {
      rincianPekerjaanList
          .removeWhere((element) => element.description == desc);
    });
  }

该 ID 列表将发送给提供者,如下所示:

Future<bool> updateActivity(
      Activity activity, List<int> activityDetailToBeDeleted) async {
    final response = await ActivityService()
        .updateActivity(activity.id.toString(), activity.toMap());

    if (response != null) {
      // Update Success.
      if (response.statusCode == 200) {
        var body = json.decode(response.body);
        removeActivityToList(activity);
        activity = Activity.fromMap(body['activity']);
        addActivityToList(activity);

        if (activityDetailToBeDeleted.isNotEmpty) {
          print("to be deleted is not empty.");
          print("ID to be deleted: ${activityDetailToBeDeleted.join(",")}");
          final res = await ActivityService()
              .deleteActivityDetail(activityDetailToBeDeleted.join(","));
          if (res.statusCode == 204) {
            print('ID DELETED.');
            return true;
          }
        }

        return true;
      }
      // Error unauthorized / token expired
      else if (response.statusCode == 401) {
        var reauth = await AuthProvider().refreshToken();

        if (reauth) {
          return await createActivity(activity);
        } else {
          return Future.error('unauthorized');
        }
      }

      return Future.error('server error');
    }

    return Future.error('connection failed');
  }

问题是如果列表为空,或者我没有将 id 添加到列表中,构建器上下文不为空,但是如果我将一个 id 添加到“要删除”的列表中,Navigator.pop(context)会抛出错误,因为 context 为空。我不明白为什么它会变成空。

full code in here

1 个答案:

答案 0 :(得分:1)

您的 [上下文] 必须来自 build() 方法。像这样。

void submitHandler(BuildContext context) async {
    setState(() {
      _isLoading = true;
    });

    // Mapping input field to activity model
    Activity activity = Activity(
        id: widget.activity.id,
        tanggal: _tanggalController.text,
        uraianKegiatan: _uraianKegiatanController.text,
        pic: _picController.text,
        jumlahTim: int.parse(_jumlahTimController.text),
        kendala: _kendalaController.text,
        penyelesaian: _penyelesaianController.text,
        approverUserId: selectedApprovalUser,
        rincianPekerjaan: rincianPekerjaanList,
        status: 'PENDING');

    if (widget.isEdit) {
      await Provider.of<ActivityProvider>(context, listen: false)
          .updateActivity(activity, activityDetailIdToBeDeleted);
    } else {
      await Provider.of<ActivityProvider>(context, listen: false)
          .createActivity(activity);
    }
    SchedulerBinding.instance.addPostFrameCallback((_) {
        Navigator.pop(context);
    });
  }