skip to Main Content

Here I have json response model,

{
    "success": true,
    "data": {
        "news": [
            {
                "id": 3,
                "user_id": 2,
                "title": "Where to give blood in the UAE",
                "content": "Blood is pretty important stuff.rnrnAs a result of the pandemic, donations have dipped, so there has been a big push to encourage people across Dubai to donate a bit of the red stuff. Here’s how and where to give blood in the UAE.rnrnWith ever-changing travel restrictions and guidance on vaccinations coming out all the time, it can be confusing to know where you stand when it comes to donating blood in Dubai, even for the best-intentioned of people. rnrnWe are here to cut through the noise and let you know the current cans and can’ts of where to give blood in the UAE.",
                "published_at": "2023-05-19 10:34:08",
                "created_at": "2023-05-19T10:34:08.000000Z",
                "updated_at": "2023-05-19T10:34:08.000000Z",
                "news_image": "https://idonor.ae/gallery/RN3saTT9-blooddonation_1-1200x900.jpg"
            },
        ]
    },
    "message": ""
} 

I tried to call the api via, Future method,

Future<Map<String, dynamic>> fetchBuildNews() async {
    final prefs = await SharedPreferences.getInstance();
    accessToken = prefs.getString('access_Token') ?? '';
    final Map<String, String> headers = {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer $accessToken',
    };
    final response = await http.get(Uri.parse('https://idonor.ae/api/latest-news'),
        headers: headers);
    if (await response.statusCode == 200) {
      final items = Map<String, dynamic>.from(json.decode(response.body));
      return items;
    } else {
      throw Exception('Failed to load data');
    }
  }

Then I have the container to call ListView builder ,

Widget newsList() {
    return new Positioned(
      // bottom: -1,
      bottom: 2,
      right: 5,
      left: 5,
      child: new Container(
          decoration: BoxDecoration(
              borderRadius: BorderRadius.all(Radius.circular(20))
          ),
          //color: Colors.transparent,
          height: 194.0,
          child: ListView(
            shrinkWrap: true,
            scrollDirection: Axis.horizontal,
            children: [
              buildNews(),
            ],
          )
      ),
    );
  }

Widget buildNews() => Container(
    width: 300,
    height: 185,
    child: FutureBuilder<Map<String, dynamic>>(
      future: fetchBuildNews(),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return ListView.builder(
            shrinkWrap: true,
            itemCount: snapshot.data?.length ?? 0,
            itemBuilder: (context, index) {
              return Container(
                  width: 300,
                  height: 185,
                  child:  Container(
                    height: 185.0,
                    width: MediaQuery.of(context).size.width - 100.0,
                    decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(5),
                        color: Colors.blue,
                        image:  DecorationImage(
                            image: NetworkImage(
                                "${snapshot.data![index].data.news[index].newsImage.toString()}"
                            ),
                            fit: BoxFit.cover)),
                    child:  Center(
                      child: Text(snapshot.data![index].data.news[index].title.toString(),
                        style: TextStyle(
                            fontFamily: 'Poppins, SemiBold', color: '#336699'.hexToColor(), fontSize: 18, fontWeight: FontWeight.w700),
                      ),
                    ),
                  ));
            },
          );
        } else if (snapshot.hasError) {
          print('${snapshot.error}');
          return Text('${snapshot.error}');
        }
        return  CircularProgressIndicator();
      },
    ),
  );

I tried sever methods to fetch the data from model, mostly had list issue, then tried with Map Future to get data, seems working but I cannot load the Map data with title and image to user interface. If anyone have suggestions to resolve this issue, really appreciated.

2

Answers


  1. Your news is inside the data. to render the news, you need to provide

    itemCount: (snapshot.data?['news'] as List?).length ?? 0
    
    Text("${snapshot.data?['news']?[index]['title']}"),//  check  if needed another `?`
    

    I will suggest creating model class.

    Login or Signup to reply.
  2. Try using this data model, using freezed_annotation: ^2.2.0 and json_annotation: ^4.8.1

    import 'package:freezed_annotation/freezed_annotation.dart';
    
    part 'response_news.freezed.dart';
    part 'response_news.g.dart';
    
    @Freezed(makeCollectionsUnmodifiable: false)
    class ResponseNews with _$ResponseNews {
      @JsonSerializable(explicitToJson: true)
      const factory ResponseNews({
        bool? success,
        String? message,
        ResponseNewsData? data,
      }) = _ResponseNews;
    
      factory ResponseNews.fromJson(Map<String, dynamic> json) =>
          _$ResponseNewsFromJson(json);
    }
    
    @Freezed(makeCollectionsUnmodifiable: false)
    class ResponseNewsData with _$ResponseNewsData {
      @JsonSerializable(explicitToJson: true)
      const factory ResponseNewsData({
        List<NewsObject>? news,
      }) = _ResponseNewsData;
    
      factory ResponseNewsData.fromJson(Map<String, dynamic> json) =>
          _$ResponseNewsDataFromJson(json);
    }
    
    @Freezed(makeCollectionsUnmodifiable: false)
    class NewsObject with _$NewsObject {
      @JsonSerializable(explicitToJson: true)
      const factory NewsObject({
        int? id,
        @JsonKey(name: 'user_id') int? userId,
        String? title,
        String? content,
        @JsonKey(name: 'published_at') String? publishedAt,
        @JsonKey(name: 'created_at') String? createdAt,
        @JsonKey(name: 'updated_at') String? updatedAt,
        @JsonKey(name: 'news_image') String? newsImage,
      }) = _NewsObject;
    
      factory NewsObject.fromJson(Map<String, dynamic> json) =>
          _$NewsObjectFromJson(json);
    }
    

    After that, change your method for fetching News to something like this:

    Future<ResponseNews> fetchBuildNews() async {
     final prefs = await SharedPreferences.getInstance();
     accessToken = prefs.getString('access_Token') ?? '';
     final headers = <String, String>{
       'Content-Type': 'application/json',
       'Authorization': 'Bearer $accessToken',
     };
     final response = await HTTP
         .get(Uri.parse('https://idonor.ae/api/latest-news'), headers: headers);
     if (response.statusCode == 200) {
       final items = ResponseNews.fromJson(
         json.decode(response.body) as Map<String, dynamic>,
       );
       return items;
     } else {
       throw Exception('Failed to load data');
     }
    }
    

    Once this is done, you will be able to access newsImage in this way from your FutureBuilder

    "${snapshot.data?.data?.news[index].newsImage}"
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search