无法使用 Getx Statemanagement [更新] 从 Cloud firestore 检索地图流列表以进行颤动

Can't retrieve a Stream List of map from cloud firestore for flutter using Getx Statemanagement [Updated]

我正在尝试从云 Firestore 中检索 NewsModel 的流列表,但最终失败了。代码和图片如下

我有一个集合 'news' > 文档 'USA' > 字段列表。 // 列表是一个包含地图列表的数组。我想检索此列表。

如何从 firebase 检索数据、存储在模型对象中并将模型用于 UI?

错误:

The following NoSuchMethodError was thrown building:
The method '[]' was called on null.
Receiver: null
Tried calling: [](0)

代码如下:

型号:

class NewsModel {
  String title, titleImage, brief;
  List aList;

  NewsModel({this.title, this.titleImage, this.brief, this.aList});

  factory NewsModel.fromMap(dynamic fieldData) {
    return NewsModel(
        title: fieldData['title'],
        titleImage: fieldData['titleImage'],
        brief: fieldData['brief'],
        aList: fieldData['mediaDescList']);
  }
}

控制器:

class Controller extends GetxController {
  // onInit
  @override
  void onInit() {
    finalNewsModel.bindStream(streamDemo());
    fetchDocs();
    super.onInit();
  }

  //
  Rxn<List<NewsModel>> finalNewsModel = Rxn<List<NewsModel>>();

  //
  List<NewsModel> get newsModelList => finalNewsModel.value;

  //
  Stream<List<NewsModel>> streamDemo() {
    return FirebaseFirestore.instance
        .collection('news')
        .doc('USA')
        .snapshots()
        .map((ds) {
      var mapData = ds.data();
      List mapList = mapData['list'];
      List<NewsModel> newsModelList = [];
      mapList.forEach((element) {
        newsModelList.add(NewsModel.fromMap(element));
      });
      return newsModelList;
    });
  }
}

UI:

class HomeBody extends StatefulWidget {
  @override
  _HomeBodyState createState() => _HomeBodyState();
}

class _HomeBodyState extends State<HomeBody> {

//
  final _controller = Get.put(Controller());

  //
  NewsModel _newsModel = NewsModel();

     @override
  Widget build(BuildContext context) {
    return Container(
      child: GetBuilder<Controller>(builder: (_controller) {
        if (_controller.newsModelList == null) {
          return Text('Loading');
        } else if (_controller.newsModelList.isEmpty) {
          return Text('Empty List');
        } else {
          return ListView.builder(
            itemCount: _controller.newsModelList.length,
            itemBuilder: (context, index) {
              return MyContainer(
                title: _newsModel.title[index],
                titleImage: _newsModel.titleImage[index],
              );
            },
          );
        }
      }),
    );
  }
}

错误 1:

The getter 'length' was called on null.

错误来自您下面的空检查:

    if (_controller.newsModelList.length == null) {
      return Text('Loading');
    }

您正在检查列表的长度是否为 null,但列表本身为空,因此您在 null 上调用 .length。 这就是错误提示的原因:

The getter 'length' was called on null.

解法:

您应该检查列表本身是否为空,如下所示:

    if (_controller.newsModelList == null) {
      return Text('Loading');
    }

现在如果你想检查列表是否为空,你必须先确保列表不是null,然后你可以在列表上调用.isEmpty()

然后您可以添加现有的 else 语句以显示 MyContainer 个小部件的列表。

错误2:

The following NoSuchMethodError was thrown building: The method '[]' was called on null. Receiver: null Tried calling:

此错误是因为您试图获取空对象的值。 它出现在下面的行中:

    title: _newsModel.title[index],
    titleImage: _newsModel.titleImage[index],

这是因为 _newsModel.title_newsModel.titleImage 为空,因为您在没有提供参数的情况下创建了 _newsModel 对象。

解法:

解决方案是从您的 build 方法中删除下面这一行:

      NewsModel _newsModel = NewsModel();

然后您可以从 _controller.newsModelList 列表中获取您的 _newModel 变量。

包含这两种解决方案的新 UI 代码应更新为以下代码块:

    class HomeBody extends StatefulWidget {
      @override
      _HomeBodyState createState() => _HomeBodyState();
    }
    
    class _HomeBodyState extends State<HomeBody> {
    
    //
      final _controller = Get.put(Controller());
    
         @override
      Widget build(BuildContext context) {
        return Container(
          child: Obx(() {
        if (_controller.newsModelList == null) {
          return Text('Loading');
        } else if (_controller.newsModelList.isEmpty) {
          return Text('Empty List');
        } else {
          return ListView.builder(
            itemCount: _controller.newsModelList.length,
            itemBuilder: (context, index) {
              final NewsModel _newsModel = _controller.newsModelList[index];
              return MyContainer(
                title: _newsModel.title,
                titleImage: _newsModel.titleImage,
                index: index,
              );
            },
          );
        }
      }),
        );
      }

你应该初始化一个值给 Rxn

Rxn<List<NewsModel>> finalNewsModel = Rxn<List<NewsModel>>([]);

  //change stream like this
 Stream<List<NewsModel>> streamDemo() {
    return FirebaseFirestore.instance
        .collection('news')
        .doc('USA')
        .snapshots()
        .map((ds) {
         var mapData = ds.data();
  List mapList = mapData['list'];
  List<NewsModel> newsModelList = [];
  mapList.forEach((element) {
    newsModelList.add(NewsModel.fromMap(element));
  });
  return newsModelList;
    });
  }

使用 GetX 生成器或 Obx

class HomeBody extends StatefulWidget {
  @override
  _HomeBodyState createState() => _HomeBodyState();
}

class _HomeBodyState extends State<HomeBody> {

//
  final Controller _controller = Get.put<Controller>(Controller());

  //
 

     @override
  Widget build(BuildContext context) {
    return Container(
      child: Obx((){
        if (_controller.newsModelList == null) {
          return Text('Loading');
        } else if (_controller.newsModelList.isEmpty) {
          return Text('Empty List');
        } else {
          return ListView.builder(
            itemCount: _controller.newsModelList.length,
            itemBuilder: (context, index) {
              return MyContainer(
                title: _newsModel.title[index],
                titleImage: _newsModel.titleImage[index],
              );
            },
          );
        }
      }),
    );
  }
}