今天要来带大家看一下搜寻资料,Firestore最简单的方式就是直接透过get()来拿到资料,但是如果我们今天需要增加一些筛选条件呢? 如我们要选取地区,我们总不希望我们看到的资料都是离我们很远的地方吧!! Let go~
这边layout就不贴罗,因为贴了的话太占版面了,我怕碍了大家的眼睛!
LinearLayout里面会塞checkBox,然後我们的间距跟string内容这次就不贴罗!
并且我们要新增checkBox的background,让它被点击後是有不同样式的
新增後一样到 checkBox的background来指定!
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true">
<shape android:shape="rectangle">
<corners android:radius="10dp"/>
<gradient android:startColor="#84C1FF"
android:endColor="#4EFEB3"/>
</shape>
</item>
<item android:state_checked="false">
<shape android:shape="rectangle">
<corners android:radius="10dp"/>
<gradient android:startColor="@color/light_pewter_blue"
android:endColor="@color/pewter_blue"/>
</shape>
</item>
</selector>
首先你要去xml,把每一个checkBox新增id,并且把它加入到list,而这个list里面的type会是checkBox,所以我们可以透过for回圈来判断哪一些checkBox有被点击。
来到SearchFragment来新增以下的funtion
//我们在class新增
private lateinit var areaCheckedList: MutableList<String>
private fun getAreaCheckedList(){
//list里面放所有的checkBox的id
val list = listOf<CheckBox>(binding.cbCityKeelung,binding.cbCityTaipei,binding.cbCityNewTaipei,binding.cbCityTaoyuan,binding.cbCityXinzhu,binding.cbCityXinzhuCounty
,binding.cbCityMiaoli,binding.cbCityMiaoliCounty,binding.cbCityTaichung,binding.cbCityZhanghua,binding.cbCityZhanghuaCounty,binding.cbCityNantou,binding.cbCityNantouCounty
,binding.cbCityYunlinCounty,binding.cbCityJiayi,binding.cbCityJaiyiCounty,binding.cbCityTainan,binding.cbCityGaoxiong,binding.cbCityPingtung,binding.cbCityPingtungCounty
,binding.cbCityYilan,binding.cbCityYilanCounty,binding.cbCityHualien,binding.cbCityHualienCounty,binding.cbCityTaidong,binding.cbCityTaidongCounty,binding.cbCityPenghuCounty
,binding.cbCityLudao,binding.cbCityLanyu,binding.cbCityJinmen,binding.cbCityMatus,binding.cbCityLianjiang)
//建立一个空的list,该list宣告在class下方,让我们可以等等直接传给viewModel
areaCheckedList = mutableListOf<String>()
for (i in list){
if (i.isChecked){
//透过i.text.toString()来拿到我们在xml里面设定的text
areaCheckedList.add(i.text.toString())
}
}
}
petType的方式也是同理
private lateinit var petTypeCheckedList: MutableList<String>
private fun getPetTypeCheckedList(){
val list = listOf<CheckBox>(binding.cbPetTypeDog,binding.cbPetTypeCat,binding.cbPetTypeRabbit,binding.cbPetTypeBird,binding.cbPetTypePig,binding.cbPetTypeFish,binding.cbPetTypeOther)
petTypeCheckedList = mutableListOf<String>()
for (i in list){
if (i.isChecked){
petTypeCheckedList.add(i.text.toString())
}
}
}
binding.btnSearchSubmit.setOnClickListener {
getAreaCheckedList()
getPetTypeCheckedList()
matchingViewModel.searchInvitation(areaCheckedList,petTypeCheckedList,this)
}
我们透过when来判断我们的使用者是否有点击checkBox
//livedata,我们分两个livedata,这个是搜寻过後的livedata
private val _dashboardInvitationList = MutableLiveData<List<Invitation>>()
val dashboardInvitationList: LiveData<List<Invitation>>
get() = _dashboardInvitationList
fun searchInvitation(areaList: MutableList<String>,petTypeList: MutableList<String>,fragment: SearchFragment){
when{
//如果地区的地方有点击但是种类没点击
areaList.isNotEmpty()&& petTypeList.isEmpty()->{
Firebase.firestore.collection(Constant.INVITATION)
//透过whereIn来塞入list,来比较资料
.whereIn(Constant.AREA,areaList)
.get()
.addOnSuccessListener{
val list =mutableListOf<Invitation>()
for(i init.documents){
val model = i.toObject(Invitation::class.java)
model?.let{
list.add(it)
}
}
_dashboardInvitationList.postValue(list)
fragment.searchInvitationSuccess(list.size)
}
.addOnFailureListener{
fragment.searchInvitationFail(it.toString())
}
}
//地区没被点,但是宠物有被点
areaList.isEmpty()&& petTypeList.isNotEmpty()->{
Firebase.firestore.collection(Constant.INVITATION)
.whereIn(Constant.PET_TYPE,petTypeList)
.get()
.addOnSuccessListener{
val list =mutableListOf<Invitation>()
for(i init.documents){
val model = i.toObject(Invitation::class.java)
model?.let{
list.add(model)
}
}
_dashboardInvitationList.postValue(list)
fragment.searchInvitationSuccess(list.size)
}
.addOnFailureListener{
fragment.searchInvitationFail(it.toString())
}
}
//如果地区的地方跟种类都有点击
areaList.isNotEmpty()&& petTypeList.isNotEmpty()->{
val ref = Firebase.firestore.collection(Constant.INVITATION)
//先搜寻地区,地区符合才进行下一步筛选
ref.whereIn(Constant.AREA,areaList)
.get()
.addOnSuccessListener{
val list =mutableListOf<Invitation>()
for(eachModel init.documents){
val model = eachModel.toObject(Invitation::class.java)
//再用for回圈来得到地区符合的这些结果里面,又符合宠物种类的
for(type in petTypeList){
model?.let{
if(model.pet_type == type){
list.add(model)
}
}
}
}
_dashboardInvitationList.postValue(list)
fragment.searchInvitationSuccess(list.size)
}
.addOnFailureListener{
fragment.searchInvitationFail(it.toString())
}
}
//需要加入else,checkBox全部都没有被点击
else ->{
Firebase.firestore.collection(Constant.INVITATION)
.get()
.addOnSuccessListener{
val list =mutableListOf<Invitation>()
for(i init.documents){
val model = i.toObject(Invitation::class.java)
model?.let{
list.add(model)
}
}
_dashboardInvitationList.postValue(list)
fragment.searchInvitationSuccess(list.size)
}
.addOnFailureListener{
fragment.searchInvitationFail(it.toString())
}
}
}
}
★我们这边要注意,Firestore搜寻有几个限制
这也是为什麽我们要area区域跟pet_type区域都有点击的时候,用for回圈来新增list。
有兴趣的小夥伴们可以参考:https://firebase.google.com/docs/firestore/query-data/queries?hl=zh-cn
并且回到searchFragment来新增以下的funtion
fun searchInvitationSuccess(resultSize: Int){
//我们从viewModel传回资料,如果回传的资料是0,我们就说没有找到资料,如果有则跳回 DashboardFragment
if (resultSize != 0 && findNavController().currentDestination?.id == R.id.searchFragment){
findNavController().navigate(R.id.action_searchFragment_to_navigation_dashboard)
}else{
showSnackBar("没有找到符合的资料",false)
}
}
fun searchInvitationFail(e: String){
showSnackBar(e,true)
}
因为我们的getAllInvitation(),写在我们的onCreateView,所以当我们的SearchFragment回来的时候,他又会再叫一次getAllInvitation,这样就有点资料又会被覆盖上去,所以这也是为什麽我们需要把searchInvitation的结果放在另一个livedata
改写一下观察
//这个资料是我们透过search得到的资料
matchingViewModel.dashboardInvitationList.observe(viewLifecycleOwner, Observer {
dashboardAdapter.submitList(it)
})
//这个则是一开始得到的资料,我们让它观测,如果改变後,并且dashboardInvitationList是null的话,才把资料塞到adapter
matchingViewModel.allInvitationList.observe(viewLifecycleOwner, Observer {
if (matchingViewModel.dashboardInvitationList.value == null){
dashboardAdapter.submitList(it)
}else{
Timber.d("dashboardInvitation里面有资料啦 不用更新")
}
})
这样就大功告成啦!
>>: Day 15: 范式概述、结构化设计 (待改进中... )
同步发表於个人网站 Meta Programming / 元程序设计 元程序设计(英语:Metap...
天亮了 昨晚是平安夜 关於迷雾森林故事 悍跳 兔兔就这样使出吃奶的力气让大家停下舞步 兔兔暴怒地大喊...
闭包 内部函数总是可以访问其所在的外部函数中声明的参数和变数,即使外部函式已经结束执行了。 看看这个...
引言 不好意思,作者总是有说不完的序言! 「机派X」的由来源自於无人机的机、树莓派的派还有 Linu...
30 - A Chain adding function Don't say so much, ju...