일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Android
- 데스크셋업
- 카카오
- Git
- GetX
- 데스크테리어
- 내돈내산
- sqflite
- AppBar
- GitHub
- 간단리뷰
- wrap
- Flutter
- visualstudiocode
- swift
- TextField
- react
- 춘식
- M1
- datetime
- AppleSilicon
- 플러터
- xcode
- ios
- 라이언
- database
- list
- error
- listview
- VSCode
- Today
- Total
welcome to my blog
[Flutter] SmartRefresher 정리 본문
리스트뷰를 하단으로 스크롤하면서 데이터를 그때그때 받아 올 때 사용할 만한 라이브러리
사용 라이브러리
pull_to_refresh: ^2.0.0
dio: ^4.0.4
사용 플러그인
FlutterJsonBeanFactory 4.3.2
임시로 데이터가 필요하기때문에 instantwebtools.net의 fake rest api 를 이용하여 테스트 해보겠다.
https://instantwebtools.net/fake-rest-api
FAKE API -> Available Endpoints
사용한 url :
https://api.instantwebtools.net/v1/passenger?page=0&size=10
url을 입력하면 해당 결과값을 json 형태로 보여줌
https://jsonformatter.curiousconcept.com/#
본격 시작
데이터 가져오기
다음 url을 https://jsonformatter.curiousconcept.com/# 의 JSON Data/URL에 넣고 결과값을 받는다.
https://api.instantwebtools.net/v1/passenger?page=0&size=10
결과값이 아래 나온다.
생성할 클래스 이름을 작성해주고 아래에는 결과값으로 반환된 값을 넣어준다.
passenger_model_entity.dart 파일(model)과 generated 폴더 등 자동으로 생성됨
stateful widget을 하나 만든다 (예제에서는 TestHomePage)
변수 정의
/// 현재 페이지 정보
int currentPage = 1;
/// 전체 페이지 정보
late int totalPages;
/// 수신 데이터 리스트
List<PassengerModelData>? passengers = [];
/// Refresher controller 생성
/// initialRefresh : SmartRefresher가 초기화되면 즉시 requestRefresh를 호출합니다.
final RefreshController refreshController =
RefreshController(initialRefresh: true);
scaffold의 body에 SmartRefresher 추가
SmartRefresher 추가
SmartRefresher의 controller에 refreshController 연결. child에는 ListView 추가
onRefresh, onLoading 에 다음코드 추가
onRefresh : 콜백이 발생하면 [RefreshController]를 사용하여 새로 고침 상태를 종료해야 합니다. 그렇지 않으면 새로 고침 상태를 유지합니다.
onLoading : 콜백이 발생하면 [RefreshController]를 사용하여 로드 상태를 종료해야 합니다. 그렇지 않으면 로드 상태를 유지합니다.
onRefresh: () async {
final result = await getPassengerData(isRefresh: true);
if (result) {
refreshController.refreshCompleted();
} else {
refreshController.refreshFailed();
}
},
onLoading: () async {
final result = await getPassengerData();
if (result) {
refreshController.loadComplete();
} else {
refreshController.loadFailed();
}
},
getPassengerData 함수 정의
Future<bool> getPassengerData({bool isRefresh = false}) async {
if (isRefresh) {
/// 리스트뷰 상단에서 아래쪽으로 내리는 동작을 하면 refresh true
/// currentpage를 1로 해서 목록을 초기화 시킴
currentPage = 1;
} else {
/// 전체 페이지보다 현재 페이지가 크면 => 마지막 페이지면 더이상 로드 할 게 없음
if (currentPage >= totalPages) {
refreshController.loadNoData();
return false;
}
}
/// size 에 넣은 값 만큼 개수를 가져온다.
String url =
"https://api.instantwebtools.net/v1/passenger?page=$currentPage&size=20";
/// Dio 라이브러리를 이용하여 url 의 응답을 받아온다.
final response = await Dio().get(url);
/// 정상 응답일 경우
if (response.statusCode == 200) {
PassengerModelEntity tempIteaam = PassengerModelEntity();
/// result에 파싱한 데이터를 넣는다.
final result = $PassengerModelEntityFromJson(response.data);
/// 새로고침 인 경우 passengers 리스트변수를 해당 값으로 초기화
if (isRefresh) {
passengers = result.data;
} else {
/// 새로고침이 아닌경우(최 하단에서 올리는 동작인 경우) passengers변수에 데이터 이어붙임
passengers!.addAll(result.data!);
}
/// 현재 페이지 +1
currentPage++;
totalPages = result.totalPages!;
/// 수신된 데이터 확인
print(response.data);
/// 변수 업데이트
setState(() {});
return true;
} else {
return false;
}
}
수신된 response 데이터를 이용하여 ListView UI에 자유롭게 표현해주면 됨
[전체 코드]
/// test_future.dart
import 'package:abcworks/generated/json/passenger_model_entity.g.dart';
import 'package:abcworks/screens/main/my/passenger_model_entity.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
Future<void> main() async {
runApp(MaterialApp(
title: "test title",
home: TestHomePage(),
));
}
class TestHomePage extends StatefulWidget {
const TestHomePage({Key? key}) : super(key: key);
@override
_TestHomePageState createState() => _TestHomePageState();
}
class _TestHomePageState extends State<TestHomePage> {
int currentPage = 1;
late int totalPages;
List<PassengerModelData>? passengers = [];
final RefreshController refreshController =
RefreshController(initialRefresh: true);
Future<bool> getPassengerData({bool isRefresh = false}) async {
if (isRefresh) {
currentPage = 1;
} else {
if (currentPage >= totalPages) {
refreshController.loadNoData();
return false;
}
}
String url =
"https://api.instantwebtools.net/v1/passenger?page=$currentPage&size=20";
final response = await Dio().get(url);
if (response.statusCode == 200) {
PassengerModelEntity tempIteaam = PassengerModelEntity();
final result = $PassengerModelEntityFromJson(response.data);
if (isRefresh) {
passengers = result.data;
} else {
passengers!.addAll(result.data!);
}
currentPage++;
totalPages = result.totalPages!;
print(response.data);
setState(() {});
return true;
} else {
return false;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("test future builder"),
),
body: SmartRefresher(
controller: refreshController,
enablePullUp: true,
onRefresh: () async {
final result = await getPassengerData(isRefresh: true);
if (result) {
refreshController.refreshCompleted();
} else {
refreshController.refreshFailed();
}
},
onLoading: () async {
final result = await getPassengerData();
if (result) {
refreshController.loadComplete();
} else {
refreshController.loadFailed();
}
},
child: ListView.separated(
itemBuilder: (context, index) {
final passenger = passengers![index];
return ListTile(
title: Text(passenger.name!),
subtitle: Column(
children: [
Image(image: NetworkImage(passenger.airline![0].logo!), height: 30, width: 30, ),
Text(passenger.airline![0].country!)
],
),
trailing: Text(index.toString()),
);
},
separatorBuilder: (context, index) => Divider(),
itemCount: passengers!.length),
),
);
}
}
/// passenger_model_entity.dart
import 'dart:convert';
import 'package:abcworks/generated/json/base/json_field.dart';
import 'package:abcworks/generated/json/passenger_model_entity.g.dart';
@JsonSerializable()
class PassengerModelEntity {
int? totalPassengers;
int? totalPages;
List<PassengerModelData>? data;
PassengerModelEntity();
factory PassengerModelEntity.fromJson(Map<String, dynamic> json) => $PassengerModelEntityFromJson(json);
Map<String, dynamic> toJson() => $PassengerModelEntityToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
@JsonSerializable()
class PassengerModelData {
@JSONField(name: "_id")
String? sId;
String? name;
int? trips;
List<PassengerModelDataAirline>? airline;
@JSONField(name: "__v")
int? iV;
PassengerModelData();
factory PassengerModelData.fromJson(Map<String, dynamic> json) => $PassengerModelDataFromJson(json);
Map<String, dynamic> toJson() => $PassengerModelDataToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
@JsonSerializable()
class PassengerModelDataAirline {
int? id;
String? name;
String? country;
String? logo;
String? slogan;
@JSONField(name: "head_quaters")
String? headQuaters;
String? website;
String? established;
PassengerModelDataAirline();
factory PassengerModelDataAirline.fromJson(Map<String, dynamic> json) => $PassengerModelDataAirlineFromJson(json);
Map<String, dynamic> toJson() => $PassengerModelDataAirlineToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
https://pub.dev/packages/pull_to_refresh
'Flutter' 카테고리의 다른 글
[Flutter] 아이폰 빌드 / Developer Mode Disabled (0) | 2023.02.09 |
---|---|
[Flutter] 윤년계산하기 - dart (0) | 2022.03.22 |
[Flutter] RxMap 사용 (0) | 2022.01.20 |
[Flutter] Wrap, Chip, FlowLayout (0) | 2022.01.11 |
[Flutter ]textbuttonTheme (0) | 2022.01.11 |