Метод '[]' был вызван с нулевым значением. Получатель: null Пробовал позвонить: [] (0)! Что я здесь делаю не так?

════════ Исключение, обнаруженное библиотекой виджетов. 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. "
    }
]

person Nikash Deka    schedule 17.11.2020    source источник
comment
Также я хотел переместить loadMessageFromAsset () и getMessagesFromAsset () в другой файл в разделе services. В таком случае, как мне получить его данные в message_screen.dart?   -  person Nikash Deka    schedule 17.11.2020


Ответы (2)


Есть несколько вещей, которые, я думаю, вы делаете неправильно.

  • Вы вызываете метод getMessagesFromAsset в двух местах: initState & FutureBuilder. Удалить из initState.

  • Вашему методу getMessageskFromAsset может потребоваться использовать другое имя переменной в методе карты:

    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`
    
person Ravi Singh Lodhi    schedule 17.11.2020
comment
К сожалению, упущен # itemCount. # Проверка списка сообщений на пустое значение была отличным предложением. Просто пояснение, условие connectionState уже работает, так зачем нам проверять, пуст ли список? - person Nikash Deka; 17.11.2020
comment
Также я хотел переместить loadMessageFromAsset () и getMessagesFromAsset () в другой файл в разделе services. В таком случае, как мне получить его данные в message_screen.dart? - person Nikash Deka; 17.11.2020
comment
Я не вижу условия connectionState в приведенном выше коде. Тем не менее, если сервер ответил пустым списком, вы также сможете обработать это условие. Вот почему вы должны проверить, является ли список пустым, и вернуть соответствующий виджет в соответствии с ним. - person Ravi Singh Lodhi; 18.11.2020
comment
Чтобы получить данные в message_screen.dart из других файлов, вы должны передать данные в качестве аргументов виджету MessageScreen. - person Ravi Singh Lodhi; 18.11.2020
comment
Я обновил свою базу кода с помощью connectionState с помощью виджета CircularProgressiveIndicator. Также перенесены функции загрузки и получения данных в сервисы. Теперь он работает. - person Nikash Deka; 18.11.2020

Индикатор возврата или что-то еще, когда состояние соединения ожидает.

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,
                ),
              );
            },
          );
        });
person Rajitha Udayanga    schedule 17.11.2020