Since using getX, I have decided to abandon provider because getX smells too good. The following is a record of the use of getX in the scrolling loading process. This article is translated from medium. The original address: anangnugraha.medium.com/flutter-imp…
Just began to learn writing, the level of worry, writing teaching ~~
The first is the dependency I use here, in pubspec.yaml.
#... Environment: SDK: ">=2.7.0 <3.0.0" ^3.15.0 lazy_load_scrollView: ^1.1.0 equatable: ^1.2.5 dev_dependencies: flutter_test: SDK: flutter #...Copy the code
I’m using Dio as the network request library, lazy_load_scrollView as the Listview and lazy loading.
Then look at the main function
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 ())), // You may actually need to change this to get.put (Controller()) to initialize binding: HomeBindings()), ]); }}Copy the code
Instead of MaterialApp, I use GetMaterialApp to manage routes more conveniently. I won’t go into details here.
Creating a data model
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; }}Copy the code
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;
}
Copy the code
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()); }}Copy the code
I’m going to add controller, and I’m going to create three observable variables, and I’m just going to add.obs to the variables to make them observable, and it’s going to update the UI automatically when the value of the variable changes.
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);
}
Copy the code
Finally, the UI section
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), ); },),),),); }}Copy the code
Now you have a list that you can scroll to load, and the state is entirely up to GetX.