Search code examples
flutterdartreturnwidget

info: This function has a return type of 'Widget', but doesn't end with a return statement


I am trying to work out why I am getting this error when my Streambuilder has returns

import 'package:flutter/material.dart';
    import 'package:http/http.dart' as http;
    import 'dart:async';
    import 'dart:convert';
    import 'package:google_fonts/google_fonts.dart';

    import 'package:paylaterapp/screens/MerchantDetails.dart';

    class MerchantList extends StatefulWidget {
      @override
      _MerchantListState createState() => new _MerchantListState();
    }

    class _MerchantListState extends State<MerchantList> {
      StreamController _postsController;
      final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();

      int count = 1;

      Future fetchPost([howMany = 10]) async {
        final response = await http.get('http://localhost/categories/fitness/$howMany');

        if (response.statusCode == 200) {
          return json.decode(response.body);
        } else {
          throw Exception('Failed to load merchant');
        }
      }

      loadPosts() async {
        fetchPost().then((res) async {
          _postsController.add(res);
          return res;
        });
      }

      showSnack() {
        return scaffoldKey.currentState.showSnackBar(
          SnackBar(
            content: Text('New content loaded'),
          ),
        );
      }

      Future<Null> _handleRefresh() async {
        count++;
        print(count);
        fetchPost(count).then((res) async {
          _postsController.add(res);
          showSnack();
          return null;
        });
      }

      @override
      void initState() {
        _postsController = new StreamController();
        loadPosts();
        super.initState();
      }

      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          key: scaffoldKey,
          appBar: new AppBar(
            title: Text('Explore Retailers',
                style: GoogleFonts.rubik(
                    fontWeight: FontWeight.w700
                )
            ),
            actions: <Widget>[
              IconButton(
                tooltip: 'Refresh',
                icon: Icon(Icons.refresh),
                onPressed: _handleRefresh,
              )
            ],
          ),
          body: StreamBuilder(
            stream: _postsController.stream,
            builder: (BuildContext context, AsyncSnapshot snapshot) {
              print('Has error: ${snapshot.hasError}');
              print('Has data: ${snapshot.hasData}');
              print('Snapshot Data ${snapshot.data}');

              if (snapshot.hasError) {
                return Text(snapshot.error);
              }

              if (snapshot.hasData) {
                return Column(
                  children: <Widget>[
                    Expanded(
                      child: Scrollbar(
                        child: RefreshIndicator(
                          onRefresh: _handleRefresh,
                          child: ListView.builder(
                            physics: const AlwaysScrollableScrollPhysics(),
                            itemCount: snapshot.data.length,
                            itemBuilder: (context, index) {
                              var post = snapshot.data[index];
                              return GestureDetector(
                                  onTap: () {
                                    print(post);
                                    Navigator.push(
                                      context,
                                      MaterialPageRoute(
                                          builder: (context) =>
                                              GridMerchantDetails(post)),
                                    );
                                  },
                                  child: Container(
                                      height: 160,
                                      margin: EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
                                      decoration: BoxDecoration(
                                          color: Colors.grey,
                                          image: DecorationImage(
                                              fit: BoxFit.cover,
                                              colorFilter: new ColorFilter.mode(
                                                  Colors.black.withOpacity(0.5),
                                                  BlendMode.darken),
                                              image: new NetworkImage(
                                                post['assets']['backgroundimage_url'] != null
                                                    ? 'https:' +
                                                    post['assets']['backgroundimage_url']
                                                    : 'https://images.unsplash.com/photo-1446844805183-9f5af45f89ee',
                                              ))),
                                      child: Column(
                                          mainAxisAlignment: MainAxisAlignment.center,
                                          children: <Widget>[
                                            FadeInImage.assetNetwork(
                                                image: post['assets']['logo_url'] != null
                                                    ? 'https:' + post['assets']['logo_url']
                                                    : 'https://images.unsplash.com/photo-1446844805183-9f5af45f89ee',
                                                placeholder: 'assets/images/transparent.png',
                                                width: 140,
                                                height: 140,
                                                fit: BoxFit.contain
                                            )
                                          ]
                                      )
                                  )
                              );
                           },     
                          ),
                        ),
                      ),
                    ),
                  ],
                );
              }

              if (!snapshot.hasData &&
                  snapshot.connectionState != ConnectionState.done) {
                return Text('No Merchants');
              }

              if (snapshot.connectionState != ConnectionState.done) {
                return Center(
                  child: CircularProgressIndicator(),
                );
              }


            },
          ),
        );
      }
    }

Solution

  • This issue should be fixed if you add at the end of your StreamBuilder builder a fallback return in case all else fails:

    ...
    if (snapshot.connectionState != ConnectionState.done) {
      return Center(
        child: CircularProgressIndicator(),
      );
    }
    
    // This line at the very end after the last `if` statement
    return Center(child: Text('Data unavailable'));
    

    You should also make sure you're accounting for every possibility of failure. With the connection and possible null data