GetX 关于报错 Null check operator used on a null value的解决

发布时间 2023-07-11 19:25:08作者: 新司机上路
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'logic.dart';

class GetIndexPage extends StatefulWidget {
  int count;
  GetIndexPage({required this.count, Key? key}) : super(key: key);
  @override
  State<GetIndexPage> createState() => _GetIndexPageState();
}

class _GetIndexPageState extends State<GetIndexPage> {
  late GetIndexLogic logic;
  @override
  void initState() {
    super.initState();
    logic = Get.put(GetIndexLogic(widget.count));
  }

  @override
  Widget build(BuildContext context) {
    return GetBuilder<GetIndexLogic>(builder: (_) {
      return Scaffold(
        body: Container(
          child: Column(
            children: [
              Text('测试数据:'),
              Expanded(child: _body),
            ],
          ),
        ),
      );
    });
  }

  get _body {
    if (logic.state.list.isEmpty) {
      return Container(
        child: Text('暂无数据'),
        alignment: Alignment.center,
      );
    }
    return GetBuilder<GetIndexLogic>(
        builder: (_) {
      return ListView.builder(
        itemBuilder: (c, index) {
          return Container(
            child: Text(logic.state.list[index]),
            alignment: Alignment.center,
            height: 70,
          );
        },
        itemCount: logic.state.list.length,
      );
    });
  }

  @override
  void dispose() {
    // TODO: implement dispose
    Get.delete<GetIndexLogic>();
    super.dispose();
  }
}

import 'dart:math';
import 'package:get/get.dart';
import 'state.dart';

class GetIndexLogic extends GetxController {
int count = 0;
GetIndexLogic(this.count);
final GetIndexState state = GetIndexState();

@override
void onInit() {
refreshData();
print("lw----onInit:$count");
super.onInit();
}

refreshData() {
state.list.clear();
  /// 模拟网络请求
Future.delayed(const Duration(milliseconds: 100), () {
bool res = Random().nextBool();
if (true) {
state.list.add('jack');
state.list.add('rose');
state.list.add(count.toString());
}
print("lw----res:$res--state.list:${state.list}");
update();
});
}

@override
void onClose() {
print("lw----onClose:$count");
super.onClose();
}
}

class GetIndexState {
List<String> list = [];

GetIndexState() {
///Initialize variables
}
}

以上是所有代码,也是使用getx 的常见场景。正常操作是不会有任何问题的。

但是如果网络数据响应时间变长,而且快速的进出页面,就会报错Null check operator used on a null value。

具体报错原因:由于快速的进出页面,当数据返回时,get内部已经delete了logic,  然后再重新创建新的

 

GetBuilder<GetIndexLogic>(
        builder: (_) {
      return ListView.builder(
        itemBuilder: (c, index) {
          return Container(
            child: Text(logic.state.list[index]),
            alignment: Alignment.center,
            height: 70,
          );
        },
        itemCount: logic.state.list.length,
      );
    });

 



getx内部,由于controller已经被释放,
执行 GetInstance().put<T>(controller!, tag: widget.tag); 的时候就会报错;
解决方式:
新创建
GetBuilder的时候,
 return GetBuilder<GetIndexLogic>(
      init: logic,
        builder: (_) {
      return ListView.builder(
        itemBuilder: (c, index) {
          return Container(
            child: Text(logic.state.list[index]),
            alignment: Alignment.center,
            height: 70,
          );
        },
        itemCount: logic.state.list.length,
      );
    });

 

总结:
只要不是在初始化时就创建出的GetBuilder,就需要加上init: logic,但是logic应该是当前页面持有的logic,才能保持数据的准确性,