Search code examples
flutterandroid-listviewscrollviewlazy-loading

Show empty list widget with lazy loading in flutter


Here is my code which has a list view and I am getting data from api in count 10. When I scroll and when the list empty I want to show empty list widget but in my case as soon as I get empty result it shows the empty widget but whole list become diappear. Or Emplty list widget replace the listview. Please help me to fix it.

class ReportVideoVerification extends StatefulWidget {
  final AdminUserDetails userDetails;
  final String title;

  const ReportVideoVerification({Key key, this.title, this.userDetails}) : super(key: key);

  @override
  _ReportVideoVerificationState createState() => _ReportVideoVerificationState();
}

class _ReportVideoVerificationState extends State<ReportVideoVerification> {
  TextEditingController fromDateController = TextEditingController();
  TextEditingController toDateController = TextEditingController();
  TextEditingController textController = TextEditingController();

  String fromDate = "",
      toDate = "";
  int limit = Consts.limit;
  static int page = 0; //offset
  ScrollController _sc = new ScrollController();
  bool isLoading = false;

  List<VideoVerificationReportResult> _vvList = new List();
  List<VideoVerificationReportResult> _filteredVvList;
  Future<VideoVerificationReport> _videoVerificationReportResponse;

  @override
  void initState() {
    print('init');
    
    resetFilter();
    super.initState();
    _sc.addListener(() {
      if (_sc.position.pixels == _sc.position.maxScrollExtent) {
        getVideoReportData(page);
      }
    });
  }
  @override
  void dispose() {
    print('disposes');
    page = 0;
    _sc.dispose();
    super.dispose();
  }
  


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBarWidget(
        title: (widget.title != null && widget.title.isNotEmpty)
            ? widget.title
            : "Video Verification Reports",
        actions: [
          AppBarLogo(),
        ],
      ),
      body: Column(children: [
        _searchWidget(),
        VerticalSpacing(5.0),
        Expanded(
            child: FutureBuilder<VideoVerificationReport>(
                future: _videoVerificationReportResponse,
                builder: (BuildContext context,
                    AsyncSnapshot<VideoVerificationReport> snapshot) {
                  if (snapshot.hasData) {
                    if (snapshot.data.result != null &&
                        snapshot.data.result.length != 0) {
                      return _buildList();
                    }
                    else
                       { return EmptyListWidget() ; }
                  } else {
                    return Center(child: LoadingIndicatorWidget());
                  }
                }))
      ]),
      resizeToAvoidBottomInset: false,
    );
  }
  Widget _buildProgressIndicator() {
    return new Padding(
      padding: const EdgeInsets.all(8.0),
      child: new Center(
        child: new Opacity(
          opacity: isLoading ? 1.0 : 00,
          child: new CircularProgressIndicator(),
        ),
      ),
    );
  }

  Widget _buildList() {
    int itemCount = _filteredVvList != null
        ? _filteredVvList.length
        : _vvList.length + 1;
    return
      ListView.builder(
        itemCount: itemCount, // Add one more item for progress indicator
        padding: EdgeInsets.symmetric(vertical: 8.0),
        itemBuilder: (BuildContext context, int index) {
          if (index == _vvList.length) {
            return _buildProgressIndicator();
          } else {
            return Column(
              children: <Widget>[
                Card(
               //list data
                ),
                if (index == _vvList.length - 1 && isLoading == false)
                  WidgetHelper.getLoaderEndText(context)
              ],
            );
          }
        },
        controller: _sc,
      );
  }

 


  Future<VideoVerificationReport> getProjectDetails() async {
    var result = await  videoVerificationReportRequest(
        context,
        widget.userDetails.result.raLoginId,
        limit.toString(),
        page.toString(),
        fromDate,
        toDate);
    return result;
  }

  getVideoReportData(int index) async {
    if (!isLoading) {
      if (this.mounted) {
        setState(() {
          isLoading = true;
        });
      }
      print('value of page:' + page.toString());
      try {
        _videoVerificationReportResponse = getProjectDetails();
        _videoVerificationReportResponse.then((response) {
          if (response != null) {
            List<VideoVerificationReportResult> result = new List();
            if (response.result != null) {
              print(response.success.toString());
              if (response.success == true) {
                result = response.result;
              } else {
                raisedToast(context, Consts.API_Msg_no_record, true, null);
              }
            }
            if (this.mounted) {
              setState(() {
                isLoading = false;
                if (response.result != null && response.result.length > 0) {
                  _vvList.addAll(result);
                }
                page = page + limit;
              });
            }
          }
        });
      } on Error catch (e) {
        print('error::: connectTimeout' + e.toString());
      }
    }
  }

}

My empty Widget :

 Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.only(top: 30),
      child: Card(
        child: ListTile(
          title: Column(
            children: <Widget>[
              Icon(
                Icons.tag_faces,
                color: Theme.of(context).primaryColor,
                size: 35.0,
              ),
              SizedBox(
                height: 5.0,
              ),
              Text(
                "No Record Found",
                textAlign: TextAlign.center,
                style: TextStyle(fontSize: 18.0, color: Colors.black87),
              ),
            ],
          ),
        ),
      ),
    );
  }

Solution

  • You can remove the length != 0 condition from this part like so

    if (snapshot.data.result != null) {
      return _buildList();
    } else { 
      return EmptyListWidget();
    }
    

    And instead handle it in _buildList() like so

    int itemCount = _filteredVvList != null
            ? _filteredVvList.length
            : _vvList.length != 0 ? _vvList.length + 1 : 0;
    

    To say so when there is no more data, you can have a bool like so

    bool noMoreData = false;
    

    and change it to true here

    if (response.result != null) {
      if (response.result.length > 0)
        _vvList.addAll(result);
      else
        noMoreData = true;
    }
    

    and use it in buildList() like so

    if (index == _vvList.length) {
      return noMoreData ? EmptyListWidget() : _buildProgressIndicator();
    }