未处理的异常:NoSuchMethod错误:类"字符串"没有实例方法"forEach"



我通过实现Bloc和Rx Dart有一个文章搜索功能。我已经成功地基于搜索的"标题"搜索文章,但是当我错误地填写"标题"时,结果并未发出错误,例如"不存在/其他任何内容",根据关键"标题",结果不是实时的,而是在LogCat中出现错误:

E/flutter (25135): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: NoSuchMethodError: Class 'String' has no instance method 'forEach'.
E/flutter (25135): Receiver: "Data not found"
E/flutter (25135): Tried calling: forEach(Closure: (dynamic) => Null)
E/flutter (25135): #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:50:5)
E/flutter (25135): #1      new Articles.fromJson (package:vallery/src/models/articles/articles.dart:11:22)
E/flutter (25135): #2      ApiProvider.searchArticle (package:vallery/src/resources/api/api_provider.dart:65:23)
E/flutter (25135): <asynchronous suspension>
E/flutter (25135): #3      Repository.searchArticlesRepository (package:vallery/src/resources/repository/repository.dart:19:74)
E/flutter (25135): #4      SearchArticleBloc.searchArticleBloc (package:vallery/src/blocs/article/articles_search_bloc.dart:12:42)
E/flutter (25135): <asynchronous suspension>
E/flutter (25135): #5      EditableTextState._formatAndSetValue (package:flutter/src/widgets/editable_text.dart:1335:14)
E/flutter (25135): #6      EditableTextState.updateEditingValue (package:flutter/src/widgets/editable_text.dart:971:5)
E/flutter (25135): #7      _TextInputClientHandler._handleTextInputInvocation (package:flutter/src/services/text_input.dart:743:36)
E/flutter (25135): <asynchronous suspension>
E/flutter (25135): #8      MethodChannel._handleAsMethodCall (package:flutter/src/services/platform_channel.dart:397:55)
E/flutter (25135): <asynchronous suspension>
E/flutter (25135): #9      MethodChannel.setMethodCallHandler.<anonymous closure> (package:flutter/src/services/platform_channel.dart:365:54)
E/flutter (25135): #10     _DefaultBinaryMessenger.handlePlatformMessage (package:flutter/src/services/binary_messenger.dart:110:33)
E/flutter (25135): <asynchronous suspension>
E/flutter (25135): #11     _invoke3.<anonymous closure> (dart:ui/hooks.dart:280:15)
E/flutter (25135): #12     _rootRun (dart:async/zone.dart:1124:13)
E/flutter (25135): #13     _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter (25135): #14     _CustomZone.runGuarded (dart:async/zone.dart:923:7)
E/flutter (25135): #15     _invoke3 (dart:ui/hooks.dart:279:10)
E/flutter (25135): #16     _dispatchPlatformMessage (dart:ui/hooks.dart:141:5)

这是模型:

class Articles {
  int status;
  List<Result> result;
  Articles({this.status, this.result});
  Articles.fromJson(Map<String, dynamic> json) {
    status = json['status'];
    if (json['result'] != null) {
      result = new List<Result>();
      json['result'].forEach((v) {
        result.add(new Result.fromJson(v));
      });
    }
  }
  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['status'] = this.status;
    if (this.result != null) {
      data['result'] = this.result.map((v) => v.toJson()).toList();
    }
    return data;
  }
}
class Result {
  String idArtikel;
  String title;
  String sinopsis;
  String content;
  String createdDate;
  String thumbnail;
  Result(
      {this.idArtikel,
        this.title,
        this.sinopsis,
        this.content,
        this.createdDate,
        this.thumbnail});
  Result.fromJson(Map<String, dynamic> json) {
    idArtikel = json['id_artikel'];
    title = json['title'];
    sinopsis = json['sinopsis'];
    content = json['content'];
    createdDate = json['created_date'];
    thumbnail = json['thumbnail'];
  }
  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['id_artikel'] = this.idArtikel;
    data['title'] = this.title;
    data['sinopsis'] = this.sinopsis;
    data['content'] = this.content;
    data['created_date'] = this.createdDate;
    data['thumbnail'] = this.thumbnail;
    return data;
  }
}

这是API:

class ApiProvider {
  Client client = Client();
  static final String baseUrl = 'link_api';
  Future<Articles> searchArticle(String title) async {
    final response = await client.post(baseUrl + 'search-artikel', body: {
      "title" : title
    });
    if (response.statusCode == 200) {
      return Articles.fromJson(json.decode(response.body));
    } else {
      throw Exception('Gagal ambil data article');
    }
  }
}

这是存储库:

class Repository {
  final apiProvider = ApiProvider();
  Future<Articles> searchArticlesRepository(String title) => apiProvider.searchArticle(title);
}

这是集团:

class SearchArticleBloc {
  final repository = Repository();
  final articleSearchFetcher = PublishSubject<Articles>();
  Observable<Articles> get allSearchArticle => articleSearchFetcher.stream;
  searchArticleBloc(String title) async {
    Articles articles = await repository.searchArticlesRepository(title);
    articleSearchFetcher.sink.add(articles);
  }
  dispose() {
    articleSearchFetcher.close();
  }
}

这是UI:

class SearchArticlePage extends StatefulWidget {
  @override
  _SearchArticlePageState createState() => _SearchArticlePageState();
}
class _SearchArticlePageState extends State<SearchArticlePage> {
  final blocSearchArticle = SearchArticleBloc();
  @override
  void dispose() {
    blocSearchArticle.dispose();
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: color_white,
      body: NestedScrollView(
        headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
          return <Widget>[
            SliverAppBar(
              backgroundColor: color_white,
              iconTheme: IconThemeData(
                color: color_blue_bg, //change your color here
              ),
              centerTitle: true,
              floating: true,
              pinned: true,
              title: TextField(
                autofocus: true,
                style: TextStyle(fontSize: 17, color: color_blue_bg),
                decoration: InputDecoration.collapsed(
                  hintText: "Article Name...",
                  hintStyle: TextStyle(fontSize: 17, color: color_blue_bg),
                ),
                onChanged: blocSearchArticle.searchArticleBloc,
              ),
            )
          ];
        },
        body: getListResult(),
      ),
    );
  }
  Widget getListResult() {
    return StreamBuilder(
      stream: blocSearchArticle.allSearchArticle,
      builder: (BuildContext context, AsyncSnapshot<Articles> snapshot) {
        if(snapshot.hasData) {
          return showListResult(snapshot);
        } else if (!snapshot.hasData) {
          return Center(
            child: Text('Data not found'),
          );
        } else if(snapshot.hasError) {
          return Text(snapshot.error.toString());
        }
        return Center(
          child: CircularProgressIndicator(),
        );
      },
    );
  }
  Widget showListResult(AsyncSnapshot<Articles> snapshot) {
    return Container(
      margin: EdgeInsets.only(top: 10.0),
      child: ListView.builder(
        shrinkWrap: true,
        physics: ClampingScrollPhysics(),
        scrollDirection: Axis.vertical,
        itemCount: snapshot.data.result == null ? Center(child: Text('Data not found')) : snapshot?.data?.result?.length ?? 0,
        itemBuilder: (BuildContext context, int index) {
          return GestureDetector(
            child: Container(
              height: MediaQuery.of(context).size.height / 7.0,
              child: Card(
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10.0),
                ),
                child: Row(
                  mainAxisSize: MainAxisSize.max,
                  children: <Widget>[
                    Container(
                      child: ClipRRect(
                        borderRadius: BorderRadius.all(Radius.circular(10.0)),
                        child: FadeInImage.assetNetwork(
                          height: MediaQuery.of(context).size.height,
                          width: MediaQuery.of(context).size.width / 3,
                          placeholder: 'assets/images/img_default_bg.png',
                          image: '${snapshot.data.result[0].thumbnail}',
                          fit: BoxFit.cover,
                        ),
                      ),
                    ),
                    Expanded(
                      child: Container(
                        margin: EdgeInsets.only(
                          left: MediaQuery.of(context).size.width / 41,
                        ),
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            Padding(
                              padding: EdgeInsets.only(
                                right: MediaQuery.of(context).size.width/41,
                                bottom: MediaQuery.of(context).size.width/ 80,
                              ),
                              child: Text(
                                snapshot.data.result[index].title,
                                overflow: TextOverflow.ellipsis,
                                maxLines: 1,
                                style: TextStyle(
                                  color: Colors.black,
                                  fontSize: MediaQuery.of(context).size.width / 25,
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                            ),
                            Padding(
                              padding: EdgeInsets.only(
                                right: MediaQuery.of(context).size.width/41,
                                bottom: MediaQuery.of(context).size.width/ 80,
                              ),
                              child: Text(
                                snapshot.data.result[index].sinopsis,
                                overflow: TextOverflow.ellipsis,
                                style: TextStyle(
                                  color: Colors.black,
                                  fontSize: MediaQuery.of(context).size.width / 35,
                                  fontWeight: FontWeight.normal,
                                ),
                              ),
                            ),
                            SizedBox(height: MediaQuery.of(context).size.height / 50,
                            ),
                            Padding(
                              padding: EdgeInsets.only(
                                right: MediaQuery.of(context).size.width/41,
                                bottom: MediaQuery.of(context).size.width/ 80,
                              ),
                              child: Text(
                                snapshot.data.result[index].createdDate,
                                style: TextStyle(
                                  color: Colors.black,
                                  fontSize: MediaQuery.of(context).size.width / 35,
                                  fontWeight: FontWeight.normal,
                                ),
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
            onTap: () {
              Navigator.push(context,
                MaterialPageRoute(builder: (context){
                  return ArticleDetailPage(
                    id: snapshot.data.result[index].idArtikel,
                    title: snapshot.data.result[index].title,
                    thumbnail: '${snapshot.data.result[index].thumbnail}',
                  );
                }),
              );
            },
          );
        },
      ),
    );
  }
}

有人可以帮我吗?因为我很头心找到解决此错误的解决方案:(

问题在这里:

if (json['result'] != null) {
  result = new List<Result>();
  json['result'].forEach((v) {
    result.add(new Result.fromJson(v));
  });
}

您期望JSON的"result"部分是列表,但显然是一个字符串。检查实际的JSON文本,您可能会找到"result": "some result",而不是"result": [ ...考虑编辑问题以显示实际的JSON。

作为一个更简单的语法可以在上面的摘要中完成您正在做的事情。(自然会出现相同的错误,直到您解决JSON数组与字符串问题。(

result = json['result'].map<Result>((j) => Result.fromJson(j).toList();

解决此问题if (json['result'] != '' && json['result'] != null) { result = new List<Result>(); json['result'].forEach((v) { result.add(new Result.fromJson(v));});}

最新更新