【发布时间】:2020-12-12 15:05:44
【问题描述】:
它需要大约 7 天的时间来尝试为延迟加载列表视图制作一个工作示例,其中提供者与现实世界的示例颤抖,但它仍然无法正常工作,因为我认为缺少某些东西
注意:第一次加载,效果很好,当我滚动它时打印(滚动)但什么也没发生,它仍然在同一页面中 如果我尝试在 _onScrollUpdated 中返回 _todolist 变量,它不会正确更改页面,三次后我看到此错误
E/flutter (7713): [错误:flutter/lib/ui/ui_dart_state.cc(166)] 未处理的异常:类型“字符串”不是类型的子类型 '列表' E/flutter (7713): #0 TodoService.fetchTodos (包:flutter_todo_provider/services/todo_service.dart:32:21)
json 示例 https://jsonformatter.org/52c83e
todos_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_todo_provider/helpers/http_exception.dart';
import 'package:provider/provider.dart';
import 'package:flutter_todo_provider/.env.dart';
import 'package:flutter_todo_provider/services/todo_service.dart';
class TodosScreen extends StatefulWidget {
@override
_TodosScreenState createState() => _TodosScreenState();
}
class _TodosScreenState extends State<TodosScreen> {
ScrollController _controller;
List<dynamic> _todoList;
bool _isLoading ;
@override
void initState() {
super.initState();
_controller = ScrollController();
_controller.addListener(_onScrollUpdated);
}
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(Configuration.AppName),
),
body: FutureBuilder(
future: _fetchListItems(),
builder: (context, snapshot){
if(snapshot.hasData){
return _listItems(snapshot.data);
}
return _buildProgressIndicator();
}
),
);
}
_fetchListItems() async {
try {
await Provider.of<TodoService>(context, listen: false).loadNextPage();
_todoList = Provider.of<TodoService>(context, listen: false).items;
} on HttpException catch (e) {
EasyLoading.showError(e.message);
}
return _todoList ;
}
Widget _listItems(data){
_isLoading = Provider.of<TodoService>(context, listen: false).isLoading ;
return ListView.builder(
controller: _controller,
itemCount: data.length ,
itemBuilder: (context, index) {
return ListTile(
title: Text(data[index].title),
subtitle:Text(data[index].content),
trailing: Icon(Icons.print),
);
},
);
}
Future<void> _onScrollUpdated() async {
print("Scroll11");
var maxScroll = _controller.position.maxScrollExtent;
var currentPosition = _controller.position.pixels;
if (currentPosition == maxScroll ) {
try {
await Provider.of<TodoService>(context, listen: false).loadNextPage();
_todoList = Provider.of<TodoService>(context, listen: false).items;
// 返回 _todoList ;如果使用此行,我会看到错误
} on HttpException catch (e) {
EasyLoading.showError(e.message);
}
}
}
Widget _buildProgressIndicator() {
_isLoading = Provider.of<TodoService>(context, listen: false).isLoading ;
return new Padding(
padding: const EdgeInsets.all(8.0),
child: new Center(
child: new Opacity(
opacity: _isLoading ? 1.0 : 00,
child: new CircularProgressIndicator(),
),
),
);
}
}
todo_service.dart
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_todo_provider/.env.dart';
import 'package:flutter_todo_provider/models/todo.dart';
class TodoService with ChangeNotifier {
bool isLoading = false;
bool isFetching = false;
int currentPage = 1;
int totalRows = 10;
List<Todo> items = [];
loadNextPage() async {
await fetchTodos(currentPage);
currentPage++;
notifyListeners();
}
Future fetchTodos(int currentPage) async {
try {
//404
var options = Options(headers: {
HttpHeaders.authorizationHeader: 'Basic ${Configuration.authToken}'
});
Map<String, dynamic> qParams = {
'current_page': currentPage,
};
Response response = await Dio().get('${Configuration.ApiUrl}/todos/my_todos', options: options, queryParameters: qParams);
List<dynamic> responseBode = response.data["data"];
responseBode.forEach(( dynamic json) {
items.add(Todo.fromJson(json));
});
notifyListeners();
} on DioError catch (e) {
print("Error Message" + e.response.statusMessage);
return items=[];
}
}
}
【问题讨论】:
-
从 initState 获取数据,移除 FutureBuilder,在您的小部件树中使用 Provider/Consumer。
-
为什么我不能使用 FutureBuilder?
-
因为 Future 构建器只会调用一次异步,并且您需要在第一次调用后再次更新小部件树。看一看:flutter.dev/docs/development/data-and-backend/state-mgmt/simple
-
问题是你需要在你的小部件树中使用消费者来接收 notifyListeners 并更新树
-
但作为文档,future builder 有自己的状态,每次数据更改时都会重建 api.flutter.dev/flutter/widgets/FutureBuilder-class.html
标签: flutter listview dart flutter-provider