自从使用getX以后果断嫌弃了provider,原因是getX太香了。 学习中发现中文资料还是很少,下面记录一下使用getX在滚动加载时的使用过程,本文是从medium上翻译的。 原文地址:anangnugraha.medium.com/flutter-imp…
刚开始学写作,水平堪忧,求写作教学~~
首先是我这里用到的依赖,在pubspec.yaml。
# ...
environment:
sdk: ">=2.7.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.0
dio: ^3.0.10
get: ^3.15.0
lazy_load_scrollview: ^1.1.0
equatable: ^1.2.5
dev_dependencies:
flutter_test:
sdk: flutter
# ...
我这里使用了Dio作为网络请求库,lazy_load_scrollview作为Listview而且支持懒加载。
然后看一下main函数
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Getx Pagination',
initialBinding: ApplicationBinding(),
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
debugShowCheckedModeBanner: false,
initialRoute: '/',
getPages: [
GetPage(
name: '/',
page: () => HomeScreen(Get.find()),
//实际上你可能需要在这里换成Get.put(Controller())进行初始化
binding: HomeBindings()),
]);
}
}
我这里使用GetMaterialApp 代替了MaterialApp,可以更方便的管理路由,这里就不多说了。
创建数据模型
List<UserModel> userModelFromJson(String str) =>
List<UserModel>.from(json.decode(str).map((x) => UserModel.fromJson(x)));
String userModelToJson(List<UserModel> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class UserModel {
String id;
String name;
String username;
UserModel({this.id, this.name, this.username});
UserModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
username = json['username'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
data['username'] = this.username;
return data;
}
}
class PaginationFilter {
int page;
int limit;
@override
String toString() => 'PaginationFilter(page: $page, limit: $limit)';
@override
bool operator ==(Object o) {
if (identical(this, o)) return true;
return o is PaginationFilter && o.page == page && o.limit == limit;
}
@override
int get hashCode => page.hashCode ^ limit.hashCode;
}
class UserRepository {
Dio _dio;
UserRepository(
this._dio,
);
Future<List<UserModel>> getUsers(PaginationFilter filter) {
return _dio.get('/users', queryParameters: {
'page': filter.page,
'limit': filter.limit
}).then((value) => value?.data
?.map<UserModel>(
(u) => UserModel.fromJson(u),
)
?.toList());
}
}
加下来是 controller,这里创建了3个可观察变量,只需要在变量后面加上.obs即可变成可观察变量,当变量值改变时自动会更新UI。
class HomeController extends GetxController {
final UserRepository _userRepository;
final _users = <UserModel>[].obs;
final _paginationFilter = PaginationFilter().obs;
final _lastPage = false.obs;
HomeController(this._userRepository);
List<UserModel> get users => _users.toList();
int get limit => _paginationFilter.value.limit;
int get _page => _paginationFilter.value.page;
bool get lastPage => _lastPage.value;
@override
onInit() {
ever(_paginationFilter, (_) => _getAllUsers());
_changePaginationFilter(1, 15);
super.onInit();
}
Future<void> _getAllUsers() async {
final usersData = await _userRepository.getUsers(_paginationFilter.value);
if (usersData.isEmpty) {
_lastPage.value = true;
}
_users.addAll(usersData);
}
void changeTotalPerPage(int limitValue) {
_users.clear();
_lastPage.value = false;
_changePaginationFilter(1, limitValue);
}
void _changePaginationFilter(int page, int limit) {
_paginationFilter.update((val) {
val.page = page;
val.limit = limit;
});
}
void loadNextPage() => _changePaginationFilter(_page + 1, limit);
}
最后是UI部分了
class HomeScreen extends StatelessWidget {
final HomeController _controller;
const HomeScreen(this._controller, {Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
child: Scaffold(
appBar: AppBar(
title: Text("GetX Pagination"),
actions: [
PopupMenuButton(
initialValue: _controller.limit,
onSelected: (value) => _controller.changeTotalPerPage(value),
itemBuilder: (context) {
return [
CheckedPopupMenuItem(
value: 15,
checked: _controller.limit == 15,
child: Text("15 / pagination"),
),
CheckedPopupMenuItem(
value: 25,
checked: _controller.limit == 25,
child: Text("25 / pagination"),
),
CheckedPopupMenuItem(
value: 50,
checked: _controller.limit == 50,
child: Text("50 / pagination"),
)
];
})
],
),
body: Obx(() => LazyLoadScrollView(
onEndOfPage: _controller.loadNextPage,
isLoading: _controller.lastPage,
child: ListView.builder(
itemCount: _controller.users.length,
itemBuilder: (context, index) {
final user = _controller.users[index];
return ListTile(
leading: Text(user.id),
title: Text(user.name),
subtitle: Text(user.username),
);
},
),
)),
),
);
}
}
好了,这样就有了一个可以滚动加载的列表了,状态完全由GetX负责。