반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- nestjs스터디
- 기술공부
- 자료구조공부
- 스프링부트
- nestjs
- 플러터 공부
- 코테준비
- 스프링공부
- JPA공부
- Flutter
- DDD
- 프로그래머스
- 카프카
- 스프링부트공부
- 자바공부
- 알고리즘공부
- 스프링
- JPA예제
- 기술면접공부
- 코테공부
- 스프링 공부
- JPA 공부
- Axon framework
- K8S
- nestjs공부
- 플러터 개발
- Kafka
- JPA
- JPA스터디
- querydsl
Archives
- Today
- Total
DevBoi
[Flutter] FutureBuilder setState 동작 이슈 본문
반응형
리스트뷰는 문제가 없는데, Future로 관리를 하고싶은, 함수에 대해서는 동작을 하지 않는 이슈가 있다.
예를 들면 데이터가 업데이트되어 다시 위젯으로 돌아왔을때 해당 아이템에 대한 갱신이 되지않았다.
이문제로 꽤 긴시간을 보내면서 정리를 하게 된다.
child: FutureBuilder(
future: groupList,
builder: (context,AsyncSnapshot snapshot){
if (snapshot.hasData && snapshot.connectionState == ConnectionState.done) {
print(snapshot.toString());
return ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 20),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
MyGroupItem item = snapshot.data[index];
return MyGroupWidget(myGroupItem: item, refreshListFunc: _fetchData);
},);
}
else
{
return Container(
child: Center(
child: Text("Loading..."),
),
);
}
}
),
일단, 추가해준 부분은 snapshot의 커넥션 상태를 추가로 확인하는 것이다.
ConnectionState.done일때만 해당 데이터를 가져와서 뿌려주고, 아닐때는 막아준다.
class MyGroupWidget extends StatefulWidget {
MyGroupItem myGroupItem;
final Function() refreshListFunc;
MyGroupWidget({Key? key,required this.myGroupItem,required this.refreshListFunc});
@override
_MyGroupWidgetState createState() => _MyGroupWidgetState(myGroupItem: myGroupItem);
}
위에서 해당 리프레쉬 하는 함수에 대한 펑션자체를 인자로 넘겨서
다시 부모 위젯에 이벤트를 발생시킨다.
_fetchData() async {
setState((){
groupList = getMyGroupListApi(userId);
});
}
위의 비동기 이벤트 메소드는 아래와 같다.
전체 소스는 아래와 같다
import 'package:async/async.dart';
import 'package:goodshot/view/group/dto/MyGroupItem.dart';
import 'package:goodshot/view/group/http/group-httpapi.dart';
import 'package:flutter/material.dart';
import 'package:goodshot/view/group/http/my-group-httpapi.dart';
import 'package:goodshot/view/group/item/get-group-item.dart';
import 'package:goodshot/view/group/item/my-group-widget.dart';
import 'package:goodshot/view/group/screen/group-list.dart';
import 'package:goodshot/view/group/widget/create-group-popup.dart';
class MyGroupList extends StatefulWidget {
final String userId;
MyGroupList({required this.userId});
@override
_MyGroupListState createState() => _MyGroupListState(userId: userId, groupList: getMyGroupListApi(userId));
}
class _MyGroupListState extends State<MyGroupList> {
final AsyncMemoizer _memoizer = AsyncMemoizer();
String userId;
Future<List<MyGroupItem>> groupList;
_MyGroupListState({required this.userId,required this.groupList});
@override
void initState() {
super.initState();
groupList = getMyGroupListApi(userId);
}
@override
Widget build(BuildContext context) {
_fetchData() async {
setState((){
groupList = getMyGroupListApi(userId);
});
}
return Scaffold(
appBar: AppBar(
centerTitle: true,
actions:[
//드롭 다운 지역 검색 가능하도록?
]
),
body: Container(
child: FutureBuilder(
future: groupList,
builder: (context,AsyncSnapshot snapshot){
if (snapshot.hasData && snapshot.connectionState == ConnectionState.done) {
print(snapshot.toString());
return ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 20),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
MyGroupItem item = snapshot.data[index];
return MyGroupWidget(myGroupItem: item, refreshListFunc: _fetchData);
},);
}
else
{
return Container(
child: Center(
child: Text("Loading..."),
),
);
}
}
),
),
floatingActionButton: FloatingActionButton(
child: Icon(
Icons.add,
color: Colors.white,
),
backgroundColor: Colors.green,
onPressed: () {
showDialog(
context: context,
barrierDismissible: true, // 바깥 영역 터치시 닫을지 여부
builder: (BuildContext context) {
return AlertDialog(
content: CreateGroupPopUp(userId: userId),
insetPadding: const EdgeInsets.fromLTRB(0,80,0, 80),
);
}
).then((value) => {
setState((){
groupList= getMyGroupListApi(userId);
})
});
},
),
);
}
}
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:goodshot/view/group/dto/MyGroupItem.dart';
import 'package:goodshot/view/group/http/group-join-httpapi.dart';
import 'package:goodshot/view/group/widget/chip-builder.dart';
import 'package:goodshot/view/group/widget/group-detail-popup.dart';
import 'package:goodshot/view/group/widget/my-group-popup.dart';
import 'package:intl/intl.dart';
class MyGroupWidget extends StatefulWidget {
MyGroupItem myGroupItem;
final Function() refreshListFunc;
MyGroupWidget({Key? key,required this.myGroupItem,required this.refreshListFunc});
@override
_MyGroupWidgetState createState() => _MyGroupWidgetState(myGroupItem: myGroupItem);
}
class _MyGroupWidgetState extends State<MyGroupWidget> {
MyGroupItem myGroupItem;
_MyGroupWidgetState({required this.myGroupItem});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 1.1),
child: InkWell(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
ListTile(
leading: CircleAvatar(
radius: 25,
backgroundImage: NetworkImage("${myGroupItem.thumbnailImageUrl}"),
),
contentPadding: EdgeInsets.all(0),
title: Text("${myGroupItem.title}",),
subtitle: Text("${myGroupItem.nickname}",),
isThreeLine: false,
trailing:
Text("${myGroupItem.region}"),
),
Wrap(
alignment: WrapAlignment.start,
spacing: 1.0,
runSpacing: 1.0,
children: <Widget>[
Chipbuilder.build("${myGroupItem.gender}",Colors.lightGreen),
Chipbuilder.build("인원 ${myGroupItem.memberCnt}명", Colors.lightGreen),
Chipbuilder.build(
"${"${myGroupItem.date}".substring(5,7)}월"
"${"${myGroupItem.date}".substring(8,10)}일 "
"${"${myGroupItem.date}".substring(11,13)}시"
"${"${myGroupItem.date}".substring(14,16)}분",
Colors.lightGreen),
Chipbuilder.build("${myGroupItem.place}",Colors.lightGreen)
],
),
Divider(thickness: 1,),
],
),
onTap: () {
print(myGroupItem.groupNo);
showDialog(
barrierDismissible: false,
context: context, builder: (BuildContext context){
return MyGroupDetailPopup(myGroupItem: myGroupItem,sourceId: myGroupItem.sourceId);
}
).then((value) => setState((){
print('시작');
widget.refreshListFunc.call();
}));
},
),
);
}
}
class MyGroupItem {
var groupNo;
var title;
var content;
String date;
var memberCnt;
var gender;
List<String> region;
List<String> introduce_tag;
var place;
var userId;
var nickname;
var thumbnailImageUrl;
var sourceId;
MyGroupItem({
required this.groupNo,
required this.title,
required this.content,
required this.date,
required this.memberCnt,
required this.gender,
required this.region,
required this.introduce_tag,
required this.place,
required this.userId,
required this.nickname,
required this.thumbnailImageUrl,
required this.sourceId,
});
factory MyGroupItem.fromJson(dynamic json, String? userId){
MyGroupItem groupItem = MyGroupItem(
groupNo: json?['group_no'],
title: json?['title'],
content: json?['content'],
date: json?['date'],
memberCnt: json?['memberCnt'],
gender: json?['gender'],
region: List<String>.from(json?['region']),
introduce_tag: List<String>.from(json?['introduce_tag']),
place: json?['place'],
userId: json?['userId'],
thumbnailImageUrl: json?['thumbnailImageUrl'],
nickname: json?['nickname'],
sourceId: userId,
);
return groupItem;
}
factory MyGroupItem.fromMap(Map<dynamic, dynamic> map, String userId){
print('gd');
MyGroupItem groupItem = MyGroupItem(
groupNo: map['group_no'],
nickname: map['user']['nickname'],
thumbnailImageUrl: map['user']['thumbnailImageUrl'],
title: map['title'].toString(),
content: map['content'].toString(),
date: DateTime.tryParse((map['date'])).toString(),
memberCnt: map['memberCnt'],
gender: map['gender'],
region: List<String>.from(map['region']),
introduce_tag: List<String>.from(map['introduce_tag']),
place: map['place'],
userId: map['user']['userId'],
sourceId: userId,
);
return groupItem;
}
}
위와 같이하면, 네비게이션 위젯 레이어 스택에 2개이상이 쌓였다가 다시 돌아왔을때
부모 위젯의 이벤트를 발생시켜, 해당 리스트뷰에 대한 아이템 갱신을 할 수 있다는 이점이 있다.
또한 ConnectionState에 대한 조건을 분기 처리하여, 로딩중일때와 에러일때를 구분하여 핸들링 할 수 있다.
반응형
'[Mobile] > [Flutter]' 카테고리의 다른 글
[Flutter] Boiler Template 적용시 (0) | 2023.09.09 |
---|---|
[Flutter] Getx로 전역 Provider 설정 (0) | 2023.09.07 |
[Flutter] Dialog 콜백 값 핸들링 (0) | 2023.09.02 |
[Flutter] initState 이전 데이터 세팅 (0) | 2023.09.02 |
[Flutter] Chip 사용 (0) | 2023.08.28 |