반응형
시작하기
Flutter 의 ListView 위젯과 GetX를 이용해 마지막 리스트에 도달 하면 추가적인 데이터를 서버에서 가지고 오는 UI를 구현합니다. (GetX 대신 Provider나 StatefullWedget으로 변경해도 됩니다.)
GetX 사용을 위한 기본 설정들
- pubspec.yaml dependencies 추가
get: ^4.1.4
- main.dart MaterialApp → GetMaterialApp 으로 변경
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialBinding: AppBinding(),
home: Scaffold(
appBar: AppBar(
title: Text('Flutter!'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: ElevatedButton(
onPressed: () {
Get.to(() => InfiniteScrollView());
},
child: Text('Infinite Scroll View'),
),
),
],
),
),
);
}
}
- AppBinding
class AppBinding extends Bindings {
@override
void dependencies() {
Get.put(InfiniteScrollController());
}
}
Infinite Scroll Controller
class InfiniteScrollController extends GetxController {
var scrollController = ScrollController().obs;
var data = <int>[].obs;
var isLoading = false.obs;
var hasMore = false.obs;
@override
void onInit() {
_getData();
this.scrollController.value.addListener(() {
if (this.scrollController.value.position.pixels ==
this.scrollController.value.position.maxScrollExtent &&
this.hasMore.value) {
_getData();
}
});
super.onInit();
}
_getData() async {
isLoading.value = true;
await Future.delayed(Duration(seconds: 2));
int offset = data.length;
var appendData = List<int>.generate(10, (i) => i + 1 + offset);
data.addAll(appendData);
isLoading.value = false;
hasMore.value = data.length < 30;
}
reload() async {
isLoading.value = true;
data.clear();
await Future.delayed(Duration(seconds: 2));
_getData();
}
}
코드 설명
- 리스트뷰의 상태를 감지하기 위한
ScrollController
ScrollController
의 position 값을 이용해 가장 마지막 행에 도달했는지 확인
- 마지막 행에 도달한 경우
_getData
를 실행하는addListener
추가
- 리스트뷰에 표시할 데이터인
data
- 실제 서버에서 데이터를 가지고 오는 것을 시뮬레이션 하기위해 강제로 2초의 딜레이 설정
- 가지고 온 데이터의 총 갯수가 30개 이상이라면 더이상 데이터가 없는 것으로 판단
- 로딩중 이나, 다음 데이터 존재여부체크를 위한
isLoading
,hasMore
Infinite Scroll View
class InfiniteScrollView extends GetView<InfiniteScrollController> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Infinite Scroll'),
),
body: Obx(
() => Padding(
padding: const EdgeInsets.all(10.0),
child: ListView.separated(
controller: controller.scrollController.value,
itemBuilder: (_, index) {
print(controller.hasMore.value);
if (index < controller.data.length) {
var datum = controller.data[index];
return Material(
elevation: 10.0,
child: Container(
padding: const EdgeInsets.all(10.0),
child: ListTile(
leading: Icon(Icons.android_outlined),
title: Text('$datum 번째 데이터'),
trailing: Icon(Icons.arrow_forward_outlined),
),
),
);
}
if (controller.hasMore.value || controller.isLoading.value) {
return Center(child: RefreshProgressIndicator());
}
return Container(
padding: const EdgeInsets.all(10.0),
child: Center(
child: Column(
children: [
Text('데이터의 마지막 입니다'),
IconButton(
onPressed: () {
controller.reload();
},
icon: Icon(Icons.refresh_outlined),
),
],
),
),
);
},
separatorBuilder: (_, index) => Divider(),
itemCount: controller.data.length + 1,
),
),
),
);
}
}
코드설명
- GetX의
Obx
를 이용해 Reactive처리
- 기본적인
ListView
를 구성하되,itemCount
를 실제데이터 갯수 + 1로 지정- 추가된 행에서
ProgressIndicator
혹은 데이터없음 안내 표시
- 추가된 행에서
실제 동작 화면
소스 링크
반응형
'Flutter' 카테고리의 다른 글
Flutter 2.2 새롭게 추가된 것들 (0) | 2021.05.21 |
---|---|
Flutter Null Safety 적용안된 package 직접 Migration 하기 (pub.dev package) (0) | 2021.05.16 |
Flutter Engage Extended Seoul Goods! (0) | 2021.05.12 |
Flutter 앱출시 방법 (0) | 2021.04.15 |
댓글