Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] 【4.3.1】HDTRefreshController loadComplete not work when load data #121

Open
syl1207 opened this issue Jan 5, 2024 · 2 comments
Labels
bug Something isn't working

Comments

@syl1207
Copy link

syl1207 commented Jan 5, 2024

Describe the bug
demo code like below:

class _SimpleTableRefreshLoadPageState
    extends State<SimpleTableRefreshLoadPage> {

  late bool conditionSometimeFalse;

  @override
  void initState() {
    widget.user.initData(5);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Pull-to-refresh Table')),
      body: tableView(),
    );
  }

  Widget tableView() {
    final HDTRefreshController hdtRefreshController = HDTRefreshController();
    if (conditionSometimeFalse) {
      return const Center(
        child: CircularProgressIndicator(),
      );
    }
    return HorizontalDataTable(
      leftHandSideColumnWidth: 100,
      rightHandSideColumnWidth: 300,
      headerWidgets: _getTitleWidget(),
      leftSideItemBuilder: _generateFirstColumnRow,
      rightSideItemBuilder: _generateRightHandSideColumnRow,
      itemCount: widget.user.userInfo.length,
      enablePullToLoadNewData: true,
      loadIndicator:  const ClassicFooter(),
      onLoad: () async {
        debugPrint('onLoad');
        //Do sth
        await Future.delayed(const Duration(milliseconds: 500));
        hdtRefreshController.loadComplete();
      },
      htdRefreshController: hdtRefreshController,
    );
  }

i found HDTRefreshController.loadComplete() sometimes not worked ,the footer is still show loading even if the HDTRefreshController.loadComplete() has been executed。


UPDATE: after exploring a long time , i found the cause。

this bug happend because of: HDTRefreshController not has a same lifecycle as table widget;

in the demo code, HDTRefreshController will created by every build, but been seted controller only when table widget init [_HorizontalDataTableState : initState],

so , i change the code like this , but it looks strange

class _SimpleTableRefreshLoadPageState
    extends State<SimpleTableRefreshLoadPage> {

  late bool conditionSometimeFalse;

  HDTRefreshController? hdtRefreshController;

  @override
  void initState() {
    widget.user.initData(5);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Pull-to-refresh Table')),
      body: tableView(),
    );
  }

  Widget tableView() {
    if (conditionSometimeFalse) {
      hdtRefreshController = null;
      return const Center(
        child: CircularProgressIndicator(),
      );
    }
    hdtRefreshController?? HDTRefreshController();
    
    return HorizontalDataTable(
      leftHandSideColumnWidth: 100,
      rightHandSideColumnWidth: 300,
      headerWidgets: _getTitleWidget(),
      leftSideItemBuilder: _generateFirstColumnRow,
      rightSideItemBuilder: _generateRightHandSideColumnRow,
      itemCount: widget.user.userInfo.length,
      enablePullToLoadNewData: true,
      loadIndicator:  const ClassicFooter(),
      onLoad: () async {
        debugPrint('onLoad');
        //Do sth
        await Future.delayed(const Duration(milliseconds: 500));
        hdtRefreshController?.loadComplete();
      },
      htdRefreshController: hdtRefreshController,
    );
  }

Platform
All

Additional context
Add any other context about the problem here.

@syl1207 syl1207 added the bug Something isn't working label Jan 5, 2024
@MayLau-CbL
Copy link
Owner

I dont quite get the point. Is this demo from the latest 4.3.1 or master code or your project? I remember the old version example code may have similar issue, but its been a while.

@syl1207
Copy link
Author

syl1207 commented Jan 9, 2024

the version is from V4.3.1,maybe the similar issue you said is solved by the code below. but I found a different bug.

  void loadComplete() {
    // change state after ui update,else it will have a bug:twice loading
    WidgetsBinding.instance.addPostFrameCallback((_) {
      footerMode?.value = LoadStatus.idle;
    });
  }

the code below can reproduce the bug。

NOTE: need add dependencies to pubspec.yaml
flutter_hooks: ^0.20.0
hooks_riverpod: ^2.3.8

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:horizontal_data_table/horizontal_data_table.dart';

import 'data/user.dart';

class SimpleTableRefreshLoadPage extends StatefulHookConsumerWidget {
  const SimpleTableRefreshLoadPage({
    Key? key,
    required this.user,
  }) : super(key: key);
  final User user;


  @override
  ConsumerState<SimpleTableRefreshLoadPage> createState() =>
      _SimpleTableRefreshLoadPageState();
}

class _SimpleTableRefreshLoadPageState
    extends ConsumerState<SimpleTableRefreshLoadPage> {

  late bool conditionSometimeFalse;

  HDTRefreshController? hdtRefreshController;

  List<UserInfo> allData = [];

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Pull-to-refresh Table')),
      body: tableView(),
    );
  }

  Widget tableView() {
    debugPrint("-------build------");
    final allData = useState(createData());
    
    final hdtRefreshController = HDTRefreshController();

    return HorizontalDataTable(
      leftHandSideColumnWidth: 100,
      rightHandSideColumnWidth: 600,
      headerWidgets: _getTitleWidget(),
      leftSideItemBuilder: (context, index) {
        return _generateFirstColumnRow(context, index, allData);
      },
      rightSideItemBuilder: (context, index) {
        return _generateRightHandSideColumnRow(context, index, allData);
      },
      itemCount: allData.value.length,
      enablePullToLoadNewData: true,
      loadIndicator:  const ClassicFooter(),
      onLoad: () async {
        debugPrint('onLoad');
        //Do sth
        await Future.delayed(const Duration(milliseconds: 500));

        var loadedData = createData();
        allData.value += loadedData;

        debugPrint("------load more ------");
        hdtRefreshController.loadComplete();
      },
      htdRefreshController: hdtRefreshController,
    );
  }

  List<Widget> _getTitleWidget() {
    return [
      _getTitleItemWidget('Name', 100),
      _getTitleItemWidget('Status', 100),
      _getTitleItemWidget('Phone', 200),
      _getTitleItemWidget('Register', 100),
      _getTitleItemWidget('Termination', 200),
    ];
  }

  Widget _getTitleItemWidget(String label, double width) {
    return Container(
      width: width,
      height: 56,
      padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
      alignment: Alignment.centerLeft,
      child: Text(label, style: const TextStyle(fontWeight: FontWeight.bold)),
    );
  }

  Widget _generateFirstColumnRow(BuildContext context, int index, ValueNotifier<List<dynamic>> allData) {
    return Container(
      width: 100,
      height: 52,
      padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
      alignment: Alignment.centerLeft,
      child: Text(allData.value[index].name),
    );
  }

  Widget _generateRightHandSideColumnRow(BuildContext context, int index,ValueNotifier<List<dynamic>> allData) {
    final item = allData.value[index];
    return Row(
      children: <Widget>[
        Container(
          width: 100,
          height: 52,
          padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
          alignment: Alignment.centerLeft,
          child: Row(
            children: <Widget>[
              Icon(
                  item.status
                      ? Icons.notifications_off
                      : Icons.notifications_active,
                  color: item.status
                      ? Colors.red
                      : Colors.green),
              Text(item.status ? 'Disabled' : 'Active')
            ],
          ),
        ),
        Container(
          width: 200,
          height: 52,
          padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
          alignment: Alignment.centerLeft,
          child: Text(item.phone),
        ),
        Container(
          width: 100,
          height: 52,
          padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
          alignment: Alignment.centerLeft,
          child: Text(item.registerDate),
        ),
        Container(
          width: 200,
          height: 52,
          padding: const EdgeInsets.fromLTRB(5, 0, 0, 0),
          alignment: Alignment.centerLeft,
          child: Text(item.terminationDate),
        ),
      ],
    );
  }

  List<UserInfo> createData({int size = 5}) {
    Random random = Random();
    final users = <UserInfo>[];
    for (int i = 0; i < size; i++) {
      users.add(UserInfo(
          "User_$i", random.nextBool(), '+001 9999 9999', '2019-01-01', 'N/A'));
    }
    return users;
  }
}

pull up to load data for some times ,the bug appear;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants