Home > Enterprise >  Flutter, How to stay in position after lazy loading
Flutter, How to stay in position after lazy loading

Time:01-06

I am trying to build a list from http server, and would like to implement page load for large data set. I tried with lazy_load_scrollview package and follow the example, I can load additional records from the server on End of page, but when new records are loaded, the list jumps up to the first record. How could I avoid this?

int totalRecords = 0;
int recordsPerPage = 5;
int currentPage = 1;
int totalPages = 1;

List<dataRecord> dataList = [];
List<dataRecord> fullList = [];
bool isLoading = false;

//class definitions...

class searchClient extends StatefulWidget {
  @override
  _searchClientState createState() => _searchClientState();
}

class _searchClientState extends State<searchClient> {
  final _searchItemController = TextEditingController();

  @override
  void initState() {
    super.initState();
    dataList = [];
    currentPage = 1;
  }

  List<dataRecord> parseJson(String responseBody) {
    final parsed =
        convert.jsonDecode(responseBody).cast<Map<String, dynamic>>();
    return parsed.map<dataRecord>((json) => dataRecord.fromJson(json)).toList();
  }

  @override
  void dispose() {
    _searchItemController.dispose();
    super.dispose();
  }

  void loadData() async {
    setState(() {
      isLoading = true;
    });

    if (totalRecords == 0) {
      final response2 = await http.get(
        Uri.parse('http://192.168.0.8:88/searchcustomer_gettotal'  
            '?userID='  
            globals.userID.toString()  
            '&token='  
            globals.token  
            '&name='  
            _searchItemController.text),
        headers: {
          "Content-type": "application/json",
          "Accept": "application/json",
          "Connection": "Keep-Alive",
        },
      );
      Map<String, dynamic> totalMap = convert.jsonDecode(response2.body);
      var total = totals.fromJson(totalMap);
      totalRecords = total.total;
      var t = totalRecords / recordsPerPage;
      if (totalRecords < recordsPerPage) {
        totalPages = 1;
      }else if (totalRecords%recordsPerPage == 0) {
        totalPages = t.round();
      }else{
        var t = totalRecords / recordsPerPage;
        totalPages = t.round()  1;
      }
      print(totalRecords);
    }
    ;

    final response = await http.get(
      Uri.parse('http://192.168.0.8:88/searchcustomer'  
          '?userID='  
          globals.userID.toString()  
          '&token='  
          globals.token  
          '&name='  
          _searchItemController.text  
          '&pageno='  
          currentPage.toString()  
          '&perpage='  
          recordsPerPage.toString()),
      headers: {
        "Content-type": "application/json",
        "Accept": "application/json",
        "Connection": "Keep-Alive",
      },
    );
    setState(() {
      isLoading = false;
    });
    dataList = parseJson(response.body);
    fullList = List.from(fullList)..addAll(dataList);
  }

  void loadMore() {
    if (currentPage < totalPages) {
      currentPage  = 1;
      loadData();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Search Client')),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.fromLTRB(12, 10, 12, 20),
            child: TextField(
              decoration: InputDecoration(
                  border: OutlineInputBorder(), labelText: 'Search Item'),
              controller: _searchItemController,
            ),
          ),
          Container(
            height: 45,
            width: 250,
            decoration: BoxDecoration(
                color: Colors.teal, borderRadius: BorderRadius.circular(16)),
            child: TextButton(
              onPressed: () {
                totalRecords = 0;
                fullList = [];
                loadData();
              },
              child: Text(
                'Search',
                style: TextStyle(color: Colors.white, fontSize: 20),
              ),
            ),
          ),
          SizedBox(height: 20),
          isLoading
              ? Center(
                  child: Padding(
                    padding: const EdgeInsets.all(50.0),
                    child: CircularProgressIndicator(),
                  ),
                )
              : Expanded(
                  child: Padding(
                    padding: const EdgeInsets.fromLTRB(12, 0, 12, 0),
                    child: LazyLoadScrollView(
                      isLoading: isLoading,
                      onEndOfPage: () {
                        loadMore();
                      },
                      child: ListView.builder(
                          itemCount: fullList.length,
                          itemBuilder: (BuildContext context, int index) {
                            return dataCard(context, fullList, index);
                          }),
                    ),
                  ),
                ),
        ],
      ),
    );
  }
}

CodePudding user response:

Could you try removing this widget of your tree

Center(
  child: Padding(
    padding: const EdgeInsets.all(50.0),
    child: CircularProgressIndicator(),
  ),
)

in order to only have your Scrollview ?

My guess is that since you're calling the setState method at load time, your whole widget tree is rebuilt, and when your new datas are fetched the whole listview is rebuilt, losing the previous position.

I'll edit my answer with some code if this doesn't fix your problem

  • Related