【问题标题】:A value of type 'List?' can't be assigned to a variable of type 'List' Flutter Retrofit'List?' 类型的值不能分配给“列表”类型的变量 Flutter Retrofit
【发布时间】:2022-01-15 11:09:45
【问题描述】:

所以我尝试使用 Retrofit 包自动生成我的 Rest Api Get 请求以返回一个包含 url、名称和 id 的 listView。 这是我的 API 请求代码。

part 'api_request.g.dart';

@RestApi(baseUrl: "https://api.imgflip.com/get_memes")
abstract class RestClient {
  factory RestClient(Dio dio, {String baseUrl}) = _RestClient;

  @GET("/data/{memes}")
  Future<List<Meme>> getMeme();
}

@JsonSerializable()
class Meme {
  String id;
  String name;
  String url;
  String box_count;

  Meme({required this.id, required this.name, required this.url, required this.box_count});

  factory Meme.fromJson(Map<String, dynamic> json) => _$MemeFromJson(json);
  Map<String, dynamic> toJson() => _$MemeToJson(this);
}

在终端运行flutter pub run build_runner build后,我得到了下面的结果作为生成的文件。

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'api_request.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

Meme _$MemeFromJson(Map<String, dynamic> json) => Meme(
      id: json['id'] as String,
      name: json['name'] as String,
      url: json['url'] as String,
      box_count: json['box_count'] as String,
    );

Map<String, dynamic> _$MemeToJson(Meme instance) => <String, dynamic>{
      'id': instance.id,
      'name': instance.name,
      'url': instance.url,
      'box_count': instance.box_count,
    };

// **************************************************************************
// RetrofitGenerator
// **************************************************************************

class _RestClient implements RestClient {
  _RestClient(this._dio, {this.baseUrl}) {
    baseUrl ??= 'https://api.imgflip.com/get_memes';
  }

  final Dio _dio;

  String? baseUrl;

  @override
  Future<List<Meme>> getMeme() async {
    const _extra = <String, dynamic>{};
    final queryParameters = <String, dynamic>{};
    final _headers = <String, dynamic>{};
    final _data = <String, dynamic>{};
    final _result = await _dio.fetch<List<dynamic>>(_setStreamType<List<Meme>>(
        Options(method: 'GET', headers: _headers, extra: _extra)
            .compose(_dio.options, '/data/{memes}',
                queryParameters: queryParameters, data: _data)
            .copyWith(baseUrl: baseUrl ?? _dio.options.baseUrl)));
    var value = _result.data!
        .map((dynamic i) => Meme.fromJson(i as Map<String, dynamic>))
        .toList();
    return value;
  }

 

所以,主要错误在这里的 main.dart 文件中,我试图将快照数据存储到 List memes 中。我得到的错误是:

“列表?”类型的值不能分配给“列表”类型的变量。尝试改变变量的类型

FutureBuilder<List<Meme>> _buildBody(BuildContext context) {
  final client = RestClient(Dio(BaseOptions(contentType: "application/json")));
  return FutureBuilder<List<Meme>>(
    future: client.getMeme(),
    builder: (context, AsyncSnapshot<List<Meme>> snapshot) {
      if (snapshot.hasData) {

      List<Meme> memes = snapshot.data ;

        return _buildMemes(context, memes) ;
      } else if (snapshot.hasError){
        return Text('ERROR: ${snapshot.error}');
      }
      else {
        return const Center(
          child: CircularProgressIndicator(),
        );
      }
    },
  );
}

Widget _buildMemes(BuildContext context, List<dynamic> memes) {
  return ListView.builder(
    itemCount: memes.length,
    padding: const EdgeInsets.all(8),
    itemBuilder: (context, index){
      return Card(
        elevation: 4,
        child: ListTile(
          title: Text(memes[index].name),
          leading: Column(
            children: <Widget>[
              Image.network(memes[index].url)
            ],
          ),
        ),
      );
    },
  );
}

【问题讨论】:

    标签: flutter rest dart retrofit flutter-futurebuilder


    【解决方案1】:

    试试:

    List&lt;Meme&gt; memes = snapshot.data!;buildBody

    snapshot.data 具有 List&lt;Meme&gt;? 类型(一个空安全类型),您必须添加 ! 才能使其与 List&lt;Meme&gt; 一起使用

    【讨论】:

    • 试过了,它消除了语法错误。我现在有一个运行时错误。此链接中的错误图像在这里link
    【解决方案2】:

    尝试 List memes =[] 由于不可为空的标准,Flutter 改变了他们创建列表的方式

    将 dio 调用作为未来的构建器

    Dio 会返回一个 response.data

    实施

    _getdata() 异步 {

    dio = Dio(); 最终响应 = 等待 dio.get('https://your-endpoint.com'); 返回(response.data);

    }

    FutureBuilder( 未来:_getdata, 生成器:(上下文,AsyncSnapshot 快照){ if (snapshot.hasData) {

      List<Meme> memes = snapshot.data ;
    
        return memes ;
      } else if (snapshot.hasError){
        return Text('ERROR: ${snapshot.error}');
    

    【讨论】:

    • 试过了,它也删除了语法错误。我现在有一个运行时错误。此链接中的错误图像在这里link
    • 不要使用带有 dio 的未来构建器。抓住 dio 承诺 -> 然后。我将发布如何使用dio。
    猜你喜欢
    • 1970-01-01
    • 2020-10-24
    • 2021-10-08
    • 2021-08-29
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-01
    相关资源
    最近更新 更多