在 null 上调用了方法“[]”。接收者:null 尝试调用:[](0) !我在这里做错了啥? [复制]

Posted

技术标签:

【中文标题】在 null 上调用了方法“[]”。接收者:null 尝试调用:[](0) !我在这里做错了啥? [复制]【英文标题】:The method '[]' was called on null. Receiver: null Tried calling: [](0) ! What am I doing Wrong here? [duplicate]在 null 上调用了方法“[]”。接收者:null 尝试调用:[](0) !我在这里做错了什么? [复制] 【发布时间】:2021-02-28 22:56:55 【问题描述】:

════════ 小部件库捕获的异常 ═══════════════════════════════════ 以下NoSuchMethodError 被抛出建筑:方法'[]'在null上被调用。接收者: null 尝试调用:

main.dart

void main() 
  
  runApp(MyApp());


class MyApp extends StatelessWidget 
  
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: HomeScreen(title: 'Email Client App'),
    );
  

home_screen.dart

class HomeScreen extends StatelessWidget 
  HomeScreen(this.title);
  final String title;

  @override
  Widget build(BuildContext context) 
    return Scaffold(
        appBar: AppBar(
          title: Text(title),
        ),
        body: MessagesScreen());
  

message_screen.dart

import 'dart:convert';
import 'package:email_client_app/models/message.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class MessagesScreen extends StatefulWidget 
  @override
  _MessagesScreenState createState() => _MessagesScreenState();


class _MessagesScreenState extends State<MessagesScreen> 
  Future loadMessageFromAsset() async 
    await Future.delayed(Duration(seconds: 2));
    return await rootBundle.loadString("data/message.json");
  

  Future<List<Message>> getMessagesFromAsset() async 
    String jsonString = await loadMessageFromAsset();
    List<dynamic> data = json.decode(jsonString);
    List<Message> messages =
        data.map((data) => Message.fromJson(data)).toList();
    return messages;
  

  @override
  void initState() 
    getMessagesFromAsset();
    super.initState();
  

  @override
  Widget build(BuildContext context) 
    return FutureBuilder(
        future: getMessagesFromAsset(),
        builder: (context, messages) 
          List<Message> messageList = messages.data;
          return ListView.builder(
            itemCount: 5,
            itemBuilder: (context, index) 

** 这是捕获错误的地方!**

              var message = messageList[index];

--

              return ListTile(
                isThreeLine: true,
                leading: CircleAvatar(child: Text('ND')),
                title: Text(messageList[index].title),
                subtitle: Text(
                  message.body,
                  maxLines: 2,
                ),
                trailing: Icon(
                  Icons.more_horiz_outlined,
                  color: Colors.blueAccent,
                ),
              );
            ,
          );
        );
  

message.dart(消息模型类)。 # 从 message.json 中获取本地数据源

class Message 
  Message(this.title, this.body);
  String title, body;

  factory Message.fromJson(Map<String, dynamic> data) 
    return Message(title: data['title'], body: data['body']);
  

  Map<String, dynamic> toJson() 
    return 'title': title, 'body': body;
  


message.json

[
    
        "title": "Title 1",
        "body": "Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consectetur adipisci elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua."
    ,
    
        "title": "Title 2",
        "body": "Lorem ipsum dolor sit amet. "
    
]

【问题讨论】:

我还想将“loadMessageFromAsset()”和“getMessagesFromAsset()”移动到服务下的不同文件中。在那种情况下,我如何在 message_screen.dart 中获取它的数据? 【参考方案1】:

我认为你做错了几件事。

您在两个地方调用方法getMessagesFromAssetinitStateFutureBuilder。从initState 中删除。

您的方法 getMessageskFromAsset 可能需要在 map 方法中使用不同的变量名:

Future<List<Message>> getMessagesFromAsset() async 
     String jsonString = await loadMessageFromAsset();
     List<dynamic> data = json.decode(jsonString);
     List<Message> messages =
         data.map((messageData) => Message.fromJson(messageData)).toList(); // here
     return messages;
   

检查messages列表是否为null

List<Message> messageList = messages.data ?? [];

ListView.builder内部,你使用的是固定值5,这会导致索引越界异常。

return ListView.builder(
     itemCount: messages?.length ?? 0, // Use messages.length instead of `5`

【讨论】:

# itemCount 令人尴尬地错过了。 # 检查消息列表的空值是一个很好的建议。只是澄清一下,connectionState 条件已经在起作用,为什么我们需要检查列表是否为空? 我还想将“loadMessageFromAsset()”和“getMessagesFromAsset()”移动到服务下的不同文件中。在那种情况下,我如何在 message_screen.dart 中获取它的数据? 我在上面的代码中没有看到任何connectionState 条件。不过,如果服务器以空列表响应,您也应该能够处理这种情况。这就是为什么你应该检查列表是否为空并根据它返回适当的小部件。 为了从其他文件中获取message_screen.dart 中的数据,您应该将数据作为参数传递给MessageScreen 小部件。 我使用 CircularProgressiveIndicator 小部件使用 connectionState 更新了我的代码库。还将用于加载和获取数据的功能移至服务。现在可以运行了。【参考方案2】:

连接状态等待时返回指示器或任何东西。

return FutureBuilder(
        future: getMessagesFromAsset(),
        builder: (context, messages) 

          // add this one
          if (messages.connectionState == ConnectionState.waiting) 
                return Text("Loading...");
          
          List<Message> messageList = messages.data;
          return ListView.builder(
            itemCount: 5,
            itemBuilder: (context, index) 
              return ListTile(
                isThreeLine: true,
                leading: CircleAvatar(child: Text('ND')),
                title: Text(messageList[index].title),
                subtitle: Text(
                  message.body,
                  maxLines: 2,
                ),
                trailing: Icon(
                  Icons.more_horiz_outlined,
                  color: Colors.blueAccent,
                ),
              );
            ,
          );
        );

【讨论】:

以上是关于在 null 上调用了方法“[]”。接收者:null 尝试调用:[](0) !我在这里做错了啥? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

在 null 上调用了方法“[]”

SharedPreferences 在 null 颤动上调用

在 null 上调用了方法“addItem”

如何修复错误:在 null 上调用了 getter 'email'。接收者:空尝试呼叫:电子邮件

NoSuchMethodError(NoSuchMethodError:方法'[]'在null上被调用。接收者:null尝试调用:[](“title”))

尝试在 nul 对象引用上调用虚拟方法 'android.content.ContentResolverr android.id.content.Context.getContentesolver()