简体   繁体   中英

I can't get the data from JSON

I'm trying to get posts from this link: reddit.com/r/flutterdev/new.json

When building FutureBuilder I get an error. I don't know what exactly I do wrong. Maybe there is an error in serialization or I somehow put the data in Text incorrectly.

JSON serialization looks like this:

@JsonSerializable()
class PostsList {
  List<PostData> children;
  PostsList({required this.children});

  factory PostsList.fromJson(Map<String, dynamic> json) =>
      _$PostsListFromJson(json);
}

@JsonSerializable()
class PostData {
  List<Post> data;
  PostData({required this.data});

  factory PostData.fromJson(Map<String, dynamic> json) =>
      _$PostDataFromJson(json);
}

@JsonSerializable()
class Post {
  final String title;
  final String? thumbnail;
  final String? ups;
  final String? selftext;

  Post({required this.title, this.thumbnail, this.ups, this.selftext});

  factory Post.fromJson(Map<String, dynamic> json) => _$PostFromJson(json);
}

HomePage and FutureBuilder:

class _MyHomePageState extends State<MyHomePage> {
  late Future<PostsList> postsList;

  @override
  void initState() {
    super.initState();
    postsList = getPostsList();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder<PostsList>(
        future: postsList,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return ListView.builder(
                itemCount: snapshot.data?.children.length,
                itemBuilder: (context, index) {
                  return Card(
                    child: ListTile(
                      title: Text(
                          '${snapshot.data?.children[index].data[index].title}'),
                    ),
                  );
                });
          } else if (snapshot.hasError) {
            return throw Exception();
          }
          return const Center(child: CircularProgressIndicator());
        },
      ),
    );
  }
}

Future<PostsList> getPostsList() async {
  const url = 'https://reddit.com/r/flutterdev/new.json';
  final response = await http.get(Uri.parse(url));
  print(
      'Status code: ${response.statusCode}, reasonPhrase: ${response.reasonPhrase}');

  if (response.statusCode == 200) {
    return PostsList.fromJson(json.decode(response.body));
  } else {
    throw Exception('Error: ${response.reasonPhrase}');
  }
}

Exception:

════════ Exception caught by widgets library ═══════════════════════════════════
The following _Exception was thrown building FutureBuilder<PostsList>(dirty, state: _FutureBuilderState<PostsList>#ff4f3):
Exception

The relevant error-causing widget was
FutureBuilder<PostsList>
package:testovoe_finam/main.dart:44
When the exception was thrown, this was the stack
#0      _MyHomePageState.build.<anonymous closure>
package:testovoe_finam/main.dart:59
#1      _FutureBuilderState.build
package:flutter/…/widgets/async.dart:615
#2      StatefulElement.build
package:flutter/…/widgets/framework.dart:4919
#3      ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4806
#4      StatefulElement.performRebuild
package:flutter/…/widgets/framework.dart:4977
#5      Element.rebuild
package:flutter/…/widgets/framework.dart:4529
#6      BuildOwner.buildScope
package:flutter/…/widgets/framework.dart:2659
#7      WidgetsBinding.drawFrame
package:flutter/…/widgets/binding.dart:891
#8      RendererBinding._handlePersistentFrameCallback
package:flutter/…/rendering/binding.dart:370
#9      SchedulerBinding._invokeFrameCallback
package:flutter/…/scheduler/binding.dart:1146
#10     SchedulerBinding.handleDrawFrame
package:flutter/…/scheduler/binding.dart:1083
#11     SchedulerBinding._handleDrawFrame
package:flutter/…/scheduler/binding.dart:997
#15     _invoke (dart:ui/hooks.dart:151:10)
#16     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:308:5)
#17     _drawFrame (dart:ui/hooks.dart:115:31)
(elided 3 frames from dart:async)
════════════════════════════════════════════════════════════════════════════════

Try this:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class _MyHomePageState extends State<MyHomePage> {
  PostsList? _list;
  bool _isLoading = true;
  bool _hasError = false;

  @override
  void initState() {
    super.initState();
    getPostsList();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: _isLoading && !_hasError
            ? const Center(child: CircularProgressIndicator())
            : !_isLoading && _hasError
                ? Column(children: [
                    Text("Error"),
                    TextButton(
                      child: Text("refresh"),
                      onPressed: () async {
                        await getPostsList();
                      },
                    )
                  ])
                : ListView.builder(
                    itemCount: _list.children.length,
                    itemBuilder: (context, index) {
                      return Card(
                        child: ListTile(
                          title: Text(
                              '${_list!.children[index].title}'), // Try to access the data
                        ),
                      );
                    }));
  }

 getPostsList() async {
    setIsLoading(true);
    setHasError(false);
    try {
      const url = 'https://reddit.com/r/flutterdev/new.json';
      final response = await http.get(Uri.parse(url));
      print(
          'Status code: ${response.statusCode}, reasonPhrase: ${response.reasonPhrase}');

      if (response.statusCode == 200) {
        setList(response.body);
        setIsLoading(false);
      } else {
        throw Exception('Error: ${response.reasonPhrase}');
        setHasError(true);
        setIsLoading(false);
      }
    } catch (_) {
      setHasError(true);
      setIsLoading(false);
    }
  }

  setList(data) {
    if (mounted)
      setState(() {
        _list = PostsList.fromJson(json.decode(data));
      });
  }

  setIsLoading(bool value) {
    if (mounted)
      setState(() {
        _isLoading = value;
      });
  }

  setHasError(bool value) {
    if (mounted)
      setState(() {
        _hasError = value;
      });
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM