首页 > 解决方案 > 主体可能正常完成,导致返回“null”,但返回类型可能是不可为空的类型

问题描述

我正在使用新的 dart 版本 >=2.12.0 <3.0.0 并启用了 null 安全性。

我添加了我的代码以供参考。

火柴服务

import 'package:cric_app/AppUrls.dart';
import 'package:cric_app/features/home/match_model.dart';
import 'package:dio/dio.dart';
import 'package:rxdart/rxdart.dart';

class MatchesService {
  // ignore: close_sinks
  BehaviorSubject<List<MatchModel>> list = BehaviorSubject<List<MatchModel>>();

  Future<List<MatchModel>> getMatches() async {
    try {
      var matchList = await fetchMatches();
      list.add(matchList);
      return matchList;
    } catch (Exc) {
      print(Exc);
    }
  }

  Future<List<MatchModel>> fetchMatches() async {
    var dio = Dio();
    final response = await dio.post(AppUrls.getMatches);
    print(response.data);
    final body = response.data['matches'] as List;
    return body.map((dynamic json) {
      return MatchModel(
        id: json['id'] as int,
        date: json['date'] as String,
        dateGmt: json['dateTimeGMT'] as String,
        teamOne: json['team-1'] as String,
        teamTwo: json['team-2'] as String,
        tossWinnerTeam: json['toss_winner_team'] as String,
        matchStarted: json['matchStarted'] as bool,
        type: json['type'] as String,
        winnerTeam: json['winner_team'] as String,
      );
    }).toList();
  }
}

主屏幕

import 'package:cric_app/components/match_card.dart';
import 'package:cric_app/features/home/match_model.dart';
import 'package:cric_app/features/home/matches_service.dart';
import 'package:cric_app/utils.dart';
import 'package:flutter/material.dart';

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  MatchesService matchesService = MatchesService();

  @override
  void initState() {
    matchesService.getMatches();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: primary_color,
      body: SingleChildScrollView(
        child: Container(
          margin: setMargin(15, 0, 15, 0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              SizedBox(
                height: 30,
              ),
              text('Matches', Colors.white, FontWeight.bold, 23),
              SizedBox(
                height: 2,
              ),
              text("Today's live matches", Colors.white, FontWeight.bold, 18),
              StreamBuilder<List<MatchModel>>(
                stream: matchesService.list,
                initialData: null,
                builder: (context, snapshot) {
                  if (snapshot.data != null) {
                    final list = snapshot.data as List;
                    return ListView.builder(
                      itemCount: list.length,
                      itemBuilder: (BuildContext context, int index) {
                        return matchCard(context, list[index]);
                      },
                    );
                  } else {
                    return Center(
                      child: text(
                        'No live matches now',
                        Colors.white,
                        FontWeight.bold,
                        16,
                      ),
                    );
                  }
                },
              ),
              SizedBox(
                height: 10,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

我收到此错误:正文可能正常完成,导致返回“null”,但返回类型可能是不可为空的类型。尝试在末尾添加 return 或 throw 语句。

标签: flutterdartdiorxdart

解决方案


在 Dart 中,如果您的函数没有return语句,则其行为与返回相同null。例如:

dynamic doesntReturn() {
  // do nothing
}
print(doesntReturn());  // prints 'null'

在您的情况下,getMatches()是一个返回 async 的函数Future<List<MatchModel>>。但是,在您的catch块中,您不会返回任何内容,从而导致隐式return null

  Future<List<MatchModel>> getMatches() async {
    try {
      var matchList = await fetchMatches();
      list.add(matchList);
      return matchList;
    } catch (Exc) {
      print(Exc);
    }

  // "return null" added implicitly
  }

但是,您的函数不能 return null,因为它的返回类型为Future<List<MatchModel>>. 异步有点复杂,但以下同步代码具有相同的行为:

List<MatchModel> getMatches() {
  try {
    return _doSomeCalculation();
  } catch (e) {
    print(e);
  }
}

要解决此问题,您需要确保return null永远不会命中隐式。您可以:

  1. 重新抛出错误,因此getMatches()抛出:
  Future<List<MatchModel>> getMatches() async {
    try {
      var matchList = await fetchMatches();
      list.add(matchList);
      return matchList;
    } catch (Exc) {
      print(Exc);
      rethrow;
    }
  1. 返回一些其他值,也许是一个空列表?
  2. 更改getMatches为返回Future<List<MatchModel>?>
  3. 永远循环(或其他静态类型的表达式Never

我可能会推荐选项 1),但这取决于您的用例


推荐阅读