티스토리 뷰
1. 지난 시간에 설정한 '내 위치'와 '동네 범위'를 이용해 FireStore db에 저장된 게시글을 필터링한다.
2. 필터링된 게시글을 Stream+ListView이용해 모두 가져온다
내 위치를 기반으로 필터링 하기
들어가기 앞서,
필터링 하기 쉽게 하기 위해 userLocation을 String→List<String>으로 바꾸었다.
EX. '경기도 성남시 수정구 위례동' → ['경기도', '성남시 수정구, '위례동']
지난 시간에 내 위치와 동네 범위를 설정하였다. 이번에는 이 설정한 위치와 동네 범위를 이용해 Firestore db에 저장된 게시글을 필터링하고자 한다.
Query<Map<String, dynamic>> postFilterLocation = FirebaseFirestore.instance
.collection("Post")
.where("UserLocation",
arrayContains: _userProvider.locations[_userProvider.scope]);
여기서 주의할 점은 array-contains 절을 최대 하나만 사용할 수 있다.
Cloud Firestore에서 단순 및 복합 쿼리 수행 | Firebase
Firebase Summit에서 발표된 모든 내용을 살펴보고 Firebase로 앱을 빠르게 개발하고 안심하고 앱을 실행하는 방법을 알아보세요. 자세히 알아보기 이 페이지는 Cloud Translation API를 통해 번역되었습니
firebase.google.com
arrayContains을 and절하려고 아래와 같이 했는데
_firestore.collection("Post").where("userLocation", arrayContains:_userProvider.locations[0]).
where("userLocation", arrayContains:_userProvider.locations[0]).where("userLocation", arrayContains:_userProvider.locations[0])
그러면 아래와 같은 오류가 뜬다.
Querry cannot contain more than one ARRAY_CONTAINS
따라서, 원래는 userLocation의 인덱스를 설정 범위까지 모두 조사해서 필터링하려고 했는데, 해당 설정 범위 인덱스의 위치가 같은지만 비교하려고 한다.
예를 들어 현재 사용자의 Locationlist [경기도, 성남시 수정구, 위례동]이고, 범위가 1(구까지)이면, 게시글 작성한 작성자의 위치 Locationlist가 [경기도, 성남시 분당구, 야탑2동]이라면 Locationlist[0], Locationlist[1]을 모두 비교하지 않고, 범위 인덱스인 Locationlist[1]만 비교한다는 뜻이다.
필터링 된 모든 게시글의 목록 보여주기
return StreamBuilder(
stream: postFilterLocation.snapshots(),
builder: (context,
AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
}
final postDocs = snapshot.data!.docs;
return ListView.builder(
itemCount: postDocs.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
Post post = Post.fromQuerySnapshot(postDocs[index]);
print(post.content);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => GroupBuyingDetailPage(post)));
},
child: PostList(
postDocs[index]['Content'],
postDocs[index]['Title'],
postDocs[index]['Date'],
postDocs[index]['Time'],
postDocs[index]['WriterName'],
postDocs[index]['UpperCategory'],
postDocs[index]['LowerCategory'],
postDocs[index]['maxParticipants'],
postDocs[index]['curParticipants'],
postDocs[index]['Place'],
),
);
},
);
},
);
1. StreamBuilder
stream뒤에는 아까 필터링 한 Query의 snapshots()을 입력한다.
2. ListView.builder
itemCount는 전체 item의 개수로, length를 이용한다.
itemBuilder에 위젯으로 감싼 각 post에 대한 간단한 정보인 PostList를 return하게 한다.
PostList
import 'package:flutter/material.dart';
import 'package:home_alone_recipe/config/palette.dart';
class PostList extends StatelessWidget {
const PostList(
this.content,
this.title,
this.date,
this.time,
this.writerName,
this.upperCategory,
this.lowerCategory,
this.maxParticipants,
this.curParticipants,
this.place,
{Key? key})
: super(key: key);
final String content;
final String title;
final String date;
final String time;
final String writerName;
final String upperCategory;
final String lowerCategory;
final int maxParticipants;
final int curParticipants;
final String place;
String curState() {
if (maxParticipants > curParticipants) {
return "모집중";
} else {
return "모집완료";
}
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(left: 20, right: 15),
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: "${curState()} ",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
color: curState() == "모집중"
? Palette.blue
: Colors.redAccent)),
TextSpan(
text: "$title\n",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
color: Colors.black)),
WidgetSpan(
child: Icon(
Icons.people,
),
),
TextSpan(
text: " $curParticipants/$maxParticipants명 참여\n",
style: TextStyle(
fontSize: 13,
color: Colors.black,
)),
WidgetSpan(
child: Icon(
Icons.calendar_month,
),
),
TextSpan(
text: " $date $time",
style: TextStyle(
fontSize: 13,
color: Colors.black,
),
),
],
),
),
),
Container(
padding: EdgeInsets.fromLTRB(18, 10, 10, 7),
height: MediaQuery.of(context).size.width * 0.23,
width: MediaQuery.of(context).size.width * 0.98,
child: DecoratedBox(
decoration: BoxDecoration(
color: Palette.lightgrey,
borderRadius: BorderRadius.circular(7.0)),
child: Center(
child: Padding(
padding: EdgeInsets.only(left: 10, right: 10),
child: Text(
content,
style: TextStyle(
fontSize: 14,
),
overflow: TextOverflow.ellipsis,
maxLines: 3,
),
),
),
),
),
Padding(
padding: EdgeInsets.only(left: 22, right: 5, top: 5),
child: Text(
"작성자: $writerName",
style: TextStyle(fontSize: 13, color: Colors.black, height: 1.0),
),
),
Padding(
padding: const EdgeInsets.only(bottom: 15, top: 10),
child: Container(
decoration: BoxDecoration(
color: Colors.grey,
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(1),
spreadRadius: 0,
blurRadius: 2,
offset: Offset(0, 2), // changes position of shadow
),
],
),
height: 1.0,
width: 500.0,
),
),
],
);
}
}
'Flutter' 카테고리의 다른 글
Flutter 게시글 클릭해서 상세 조회하기 (0) | 2022.11.27 |
---|---|
Flutter 내 동네 설정하기-2 (Firebase) (4) | 2022.11.22 |
Flutter 내 동네 설정하기 -1 (0) | 2022.11.19 |
- Total
- Today
- Yesterday
- 빌더 패턴
- 프로토타입 패턴
- ArrayDeque
- 구글로그인
- 플라이웨이트패턴
- 상태 패턴
- jpa
- dfs
- springsecurity
- java문법
- 반복자 패턴
- Chain of Responsibility
- 메멘토 패턴
- restapi
- Flutter
- 책임연쇄패턴
- 프록시패턴
- n+1
- CompositePattern
- Iterator Pattern
- idtoken
- GithubActions
- 복합체 패턴
- 브리지 패턴
- FacadePattern
- 컴포지트패턴
- UML 필요성
- 양방향연관관계
- 퍼싸드패턴
- 책임체인패턴
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |