android – Flutter Unhealthy State: No Factor

[ad_1]

I’m attempting to develop an utility that shows a information feed from a number of RSS feeds, nevertheless, earlier than it hundreds fully, there’s the Unhealthy State: No Factor error.

First, here is the start of the code:

import 'package deal:flutter/materials.dart';
import 'package deal:flutter_slidable/flutter_slidable.dart';
import 'package deal:mitech/controllers/bookmarked_posts_controller.dart';
import 'package deal:mitech/fashions/bookmarked_posts_model.dart';
import 'package deal:webfeed/webfeed.dart';
import 'package deal:http/http.dart' as http;
import 'package deal:url_launcher/url_launcher.dart';
import 'package deal:cached_network_image/cached_network_image.dart';

class Feed extends StatefulWidget {
  const Feed({Key? key}) : tremendous(key: key);
  closing String title="Últimas atualizações";

  @override
  State<Feed> createState() => _FeedState();
}

class _FeedState extends State<Feed> {
  static const String placeholderImg = 'belongings/pictures/noImage.jpg';
  late GlobalKey<RefreshIndicatorState> _refreshKey;

  Record<Uri> feedURIs = [
    Uri(
      scheme: 'https',
      host: 'rss.tecmundo.com.br',
      path: 'feed'
    ),
  ];

  Record<RssFeed> feeds = [];

  @override
  void initState() {
    tremendous.initState();
    _refreshKey = GlobalKey<RefreshIndicatorState>();
    load();
  }

To get the feed:

Future<Record<RssFeed>?> loadFeed() async {
    strive {
      closing shopper = http.Consumer();
      
      for (Uri uri in feedURIs) {
        closing response = await shopper.get(uri);
        feeds.add(RssFeed.parse(response.physique));
      }

      return feeds;
    } catch (e) {
      //
    }
    return null;
  }

  load() async {
    loadFeed().then((outcome) {
      if (null == outcome || outcome.toString().isEmpty) {
        return showDialog(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              title: const Textual content('Erro ao carregar.'),
              content material: const Textual content('Tente novamente mais tarde.'),
              actions: [
                TextButton(
                  child: const Text('OK'),
                  onPressed: () {
                    Navigator.pop(context);
                  },
                ),
              ],
            );
          }
        );
      }
      updateFeed(outcome);
    });
  }

  updateFeed(feed) {
    setState(() {
      feeds = feed;
    });
  }

Now, the code to open the information, in addition to the sfunctions that present the title, subtitle and the picture of the information.

Future<void> openFeed (String url) async {
    closing Uri uri = Uri.parse(url);
    if(!await launchUrl(uri, mode: LaunchMode.inAppWebView)) {
      showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: const Textual content('Erro ao carregar.'),
            content material: const Textual content('Tente novamente mais tarde.'),
            actions: [
              TextButton(
                child: const Text('OK'),
                onPressed: () {
                  Navigator.pop(context);
                },
              ),
            ],
          );
        }
      );
    }
  }

  Textual content title (title) {
    return Textual content(
      title,
      type: const TextStyle(
        fontSize: 18.0,
        fontWeight: FontWeight.w500,
      ),
      maxLines: 2,
      overflow: TextOverflow.ellipsis,
      key: ValueKey('$title'),
    );
  }

  Textual content subtitle (subtitle) {
    return Textual content(
      subtitle ?? '',
      type: const TextStyle(
        fontSize: 14.0,
        fontWeight: FontWeight.w100,
      ),
      maxLines: 1,
      overflow: TextOverflow.ellipsis,
      key: ValueKey('$subtitle'),
    );
  }

  Padding thumbnail (imageUrl) {
    return Padding(
      key: ValueKey('$imageUrl'),
      padding: const EdgeInsets.solely(left: 15.0),
      baby: imageUrl != null ? CachedNetworkImage(
        placeholder: (context, url) => Picture.asset(placeholderImg),
        imageUrl: imageUrl,
        top: 50,
        width: 50,
        alignment: Alignment.heart,
        match: BoxFit.cowl,
      ) :
      SizedBox(
        top: 50,
        width: 50,
        baby: Picture.asset(placeholderImg),
      ),
    );
  }

Now the half that I feel is most vital: the itemizing half (“listragem” means “itemizing”). Right here I add the gadgets from every feed right into a vector after which add them to a ListView and show them on the display. Right here I additionally put a perform so as to add them to bookmarks, however this isn’t the issue. My suspicion is that the applying waits for this add motion to be accomplished after which the information gadgets seem on the display.

Widget listing () {
    Record<ListTile> listagem = [];
    
    for (RssFeed f in feeds) {
      for (int i = 0; i < f.gadgets!.size; i++) {
        closing merchandise = f.gadgets![i];
        listagem.add(
          ListTile(
            key: ValueKey('${merchandise.hyperlink}'),
            title: title(merchandise.title),
            subtitle: subtitle(merchandise.dc?.creator ?? 'No creator'),
            main: thumbnail(merchandise.enclosure!.url),
            trailing: const Icon(Icons.keyboard_arrow_right),
            contentPadding: const EdgeInsets.all(5.0),
            onTap: () => openFeed(merchandise.hyperlink ?? ''),
          )
        );
      }
    }

    if(listagem.isEmpty) {
      return const CircularProgressIndicator();
    }
    else {
      return ListView.builder(
      itemCount: listagem.size,
      addAutomaticKeepAlives: true,
      addRepaintBoundaries: true,
      itemBuilder: (BuildContext context, int index) {
        return Slidable(
          startActionPane: ActionPane(
            movement: const DrawerMotion(),
            kids: [
              SlidableAction(
                onPressed: (context) {
                  try {
                    BookmarkedPostsController().insert(
                      BookmarkedPostsModel(
                        null,
                        listagem[index].title?.key.toString(),
                        listagem[index].subtitle?.key.toString(),
                        listagem[index].main?.key.toString(),
                        listagem[index].key.toString(), // the hyperlink's on this line
                      )
                    );
                    
                    print(listagem[index].key.toString());
                    
                    ScaffoldMessenger.of(context).showSnackBar(
                      SnackBar(
                        backgroundColor: Colours.blue,
                        dismissDirection: DismissDirection.startToEnd,
                        conduct: SnackBarBehavior.floating,
                        content material: Row(
                          mainAxisAlignment: MainAxisAlignment.heart,
                          kids: const [
                            Icon(Icons.bookmark_added, color: Colors.white,),
                            SizedBox(width: 25,),
                            Text(
                              'A notícia foi salva com sucesso!',
                              style: TextStyle(fontFamily: 'San Francisco',),
                            ),
                          ],
                        ),
                      )
                    );

                    print('Salvou!');
                  }
                  catch (_) {
                    print('Erro!');
                    ScaffoldMessenger.of(context).showSnackBar(
                      SnackBar(
                        backgroundColor: Colours.purple,
                        dismissDirection: DismissDirection.startToEnd,
                        conduct: SnackBarBehavior.floating,
                        content material: Row(
                          kids: const [
                            Icon(Icons.error, color: Colors.white,),
                            SizedBox(width: 25,),
                            Text(
                              'Erro: não foi possível salvar a notícia!',
                              style: TextStyle(
                                fontFamily: 'San Francisco'
                              ),
                            ),
                          ],
                        ),
                      ),
                    );
                  }
                },
                backgroundColor: Colours.blue,
                foregroundColor: Colours.white,
                icon: Icons.bookmark_outline,
                label: 'Salvar'
              ),
            ],
          ),
          baby: listagem[index],
        );
      },
    );
    }
  }

This perform of checking whether or not or not RSS feeds are empty is a case aside, I’ve tried leaving it in a “lengthy kind”, however for some cause I may solely make it work this manner:

isFeedEmpty () 

This final half is the one which hundreds the physique of the applying:

Widget physique () => isFeedEmpty() ?
    const Heart(
      baby: CircularProgressIndicator(),
    ) :
    RefreshIndicator(
      onRefresh: () => load(),
      key: _refreshKey,
      baby: listing(),
    );
  
  @override
  Widget construct(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Textual content('Últimas atualizações'),
      ),
      physique: physique(),
    );
  }
}

I’ve tried placing a situation in order that if the listing array is empty, the perform returns a CircularProgressIndicator(), but it surely does not appear to work, since, I imagine, the error persists till the array is totally crammed.

if(listagem.isEmpty) {
      return const CircularProgressIndicator();
    }
    else {
      return ListView.builder(
      itemCount: listagem.size,

[ad_2]

Leave a Reply