Android 为什么当我在适配器中添加数据时,它也会更改我的LiveData?
所以我对使用体系结构组件的MVVM是新手。我想在我的回收器视图中添加加载页脚。在适配器中添加虚拟项以便在适配器中显示加载页脚后,我不明白为什么虚拟项(餐厅)也会出现在我的LiveData流中(在我的repository和RestaurantClient中,来自改装),我假设适配器和我的LiveData流之间没有连接 这是我的适配器Android 为什么当我在适配器中添加数据时,它也会更改我的LiveData?,android,kotlin,android-livedata,android-architecture-components,android-jetpack,Android,Kotlin,Android Livedata,Android Architecture Components,Android Jetpack,所以我对使用体系结构组件的MVVM是新手。我想在我的回收器视图中添加加载页脚。在适配器中添加虚拟项以便在适配器中显示加载页脚后,我不明白为什么虚拟项(餐厅)也会出现在我的LiveData流中(在我的repository和RestaurantClient中,来自改装),我假设适配器和我的LiveData流之间没有连接 这是我的适配器 class RestaurantRecyclerAdapter(var mOnItemClickedListener : OnItemClickedListener)
class RestaurantRecyclerAdapter(var mOnItemClickedListener : OnItemClickedListener): RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val ITEM_TYPE = 0
private val LOADING_TYPE = 1
var restaurantList = ArrayList<Restaurant>()
override fun getItemViewType(position: Int): Int {
if ( restaurantList[position].name == "dummy" ) {
return LOADING_TYPE
} else {
return ITEM_TYPE
}
}
fun addLoadingFooter() {
if (!isLoading) {
isLoading = true
val dummyRestaurant = Restaurant()
dummyRestaurant.name = "dummy"
restaurantList.add(dummyRestaurant)
notifyDataSetChanged()
}
}
fun removeLoadingFooter() {
isLoading = false
val index = restaurantList.indexOfFirst{
it.name == "dummy"
}
if (index != -1) {
restaurantList.removeAt(index)
notifyDataSetChanged()
}
}
类RestaurantRecyclerAdapter(var mOnItemClickedListener:OnItemClickedListener):RecyclerView.Adapter(){
私有val项_类型=0
专用val加载类型=1
var restaurantList=ArrayList()
覆盖getItemViewType(位置:Int):Int{
如果(餐厅列表[position].name==“dummy”){
返回加载类型
}否则{
返回项目类型
}
}
乐趣添加加载页脚(){
如果(!isLoading){
isLoading=true
val Dummy餐厅=餐厅()
dummy restaurant.name=“dummy”
restaurantList.add(dummyRestaurant)
notifyDataSetChanged()
}
}
有趣的电影{
isLoading=错误
val索引=restaurantList.indexOfFirst{
it.name==“虚拟”
}
如果(索引!=-1){
restaurantList.removeAt(索引)
notifyDataSetChanged()
}
}
当recycler视图到达底部时,它将触发此代码从服务器重新提取数据,这也是我的片段中列表的观察者
class RestaurantListFragment : Fragment(), OnItemClickedListener {
lateinit var model : RestaurantListViewModel
lateinit var restaurantRecyclerAdapter: RestaurantRecyclerAdapter
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
fragmentView = inflater.inflate(R.layout.fragment_restaurant_list, container, false)
model = ViewModelProvider(this).get(RestaurantListViewModel::class.java)
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
val isLoading = model.isLoading.value ?: return
val isQueryExhausted = model.isQueryHausted.value ?: return
if (!recyclerView.canScrollVertically(1) && !isLoading && !isQueryExhausted) {
model.searchNextPage()
restaurantRecyclerAdapter.addLoadingFooter() // <-- add footer in here
}
}
})
model.restaurants.observe(viewLifecycleOwner, Observer { restaurantList ->
// that dummy restaurant object I add from adapter to show loading footer
// will also show in my LiveData in 'restaurantList' in here
restaurantList?.let {
restaurantRecyclerAdapter.setRestaurants(it)
restaurantRecyclerAdapter.removeLoadingFooter() // remove footer in here
showLoadingIndicator(false)
}
})
return fragmentView
}
}
class RestaurantListFragment:Fragment(),OnItemClickedListener{
lateinit var模型:RestaurantListViewModel
lateinit var restaurantRecyclerAdapter:restaurantRecyclerAdapter
覆盖创建视图(
充气器:布局充气器,容器:视图组?,
savedInstanceState:捆绑?
):查看{
//为该碎片膨胀布局
fragmentView=充气机。充气(R.layout.fragment\u餐厅\u列表,容器,错误)
model=ViewModelProvider(this.get)(RestaurantListViewModel::class.java)
recyclerView.addOnScrollListener(对象:recyclerView.OnScrollListener(){
覆盖CrollStateChanged(recyclerView:recyclerView,newState:Int){
super.onScrollStateChanged(recyclerView、newState)
val isLoading=model.isLoading.value?:返回
val isqueryexhousted=model.isqueryhousted.value?:返回
如果(!recyclerView.CanScrollVertical(1)&&&!isLoading&&!IsQueryExhousted){
model.searchNextPage()
restaurantRecyclerAdapter.addLoadingFooter()//
//我从适配器添加的虚拟餐厅对象显示加载页脚
//也将显示在我的LiveData中的“restaurantList”中
餐厅名单?让我看看{
restaurantRecyclerAdapter.setRestaurants(it)
restaurantRecyclerAdapter.removeLoadingFooter()//删除此处的页脚
显示加载指示器(错误)
}
})
返回碎片视图
}
}
下面是该片段的viewModel
class RestaurantListViewModel : ViewModel() {
var restaurants : LiveData<ArrayList<Restaurant>> = RestaurantRepository.restaurants
fun searchRestaurants(query: String) {
RestaurantRepository.searchRestaurants(
query = query,
latitude = mLatitude,
longitude = mLongitude
)
}
fun searchNextPage() {
RestaurantRepository.searchNextPage(mLatitude,mLongitude)
}
}
class RestaurantListViewModel:ViewModel(){
var restaurants:LiveData=RestaurantRepository.restaurants
趣味搜索餐厅(查询:字符串){
餐馆(
query=query,
纬度=纬度,
经度=米长
)
}
趣味搜索下一页(){
RestaurantRepository.SearchNext页面(mLatitude,mLongitate)
}
}
这是我的存储库
object RestaurantRepository {
val restaurants: MediatorLiveData<ArrayList<Restaurant>> = MediatorLiveData()
private val restaurantsFromClient : LiveData<ArrayList<Restaurant>> = RestaurantClient.restaurants
init {
initMediators()
}
private fun initMediators() {
restaurants.addSource(restaurantsFromClient) { restaurantList ->
if (restaurantList == null) {
// get data from Room database
} else {
restaurants.postValue(restaurantList)
}
}
}
fun searchNextPage(latitude:Double, longitude: Double) {
val numberOfCurrentShowedRestaurants = restaurants.value?.size ?: return
RestaurantClient.searchRestaurants(
query = mQuery,
latitude = latitude,
longitude = longitude,
start = numberOfCurrentShowedRestaurants + NUMBER_OF_DOCUMENT_PER_PAGE
)
}
}
objectrestaurantrepository{
val:MediatorLiveData=MediatorLiveData()
private val restaurantsFromClient:LiveData=RestaurantClient.restaurants
初始化{
initMediators()
}
私人调解人(){
addSource(restaurantsFromClient){restaurantList->
如果(restaurantList==null){
//从房间数据库获取数据
}否则{
餐厅.postValue(餐厅列表)
}
}
}
趣味搜索下一页(纬度:双精度,经度:双精度){
val numberOfCurrentShowedRestaurants=餐厅。值?大小?:返回
RestaurantClient.searchRestaurants(
query=mQuery,
纬度=纬度,
经度=经度,
开始=当前显示的Restarants数量+每页文档数量
)
}
}
这是一个餐馆客户端,它使用改型从服务器检索数据
object RestaurantClient {
val restaurants = MutableLiveData<ArrayList<Restaurant>>()
private val restaurantService = RetrofitServiceGenerator.getInstance(RestaurantAPI::class.java)
fun searchRestaurants(query: String, latitude:Double, longitude: Double, start: Int) {
val call = restaurantService.searchRestaurants(
radius = 2000,
query = query,
latitude = latitude,
longitude = longitude,
start = start,
count = NUMBER_OF_DOCUMENT_PER_PAGE
)
isLoading.value = true
call.enqueue(object: Callback<RestaurantListBaseResponse> {
override fun onFailure(call: Call<RestaurantListBaseResponse>, t: Throwable) {
}
override fun onResponse(call: Call<RestaurantListBaseResponse>, response: Response<RestaurantListBaseResponse>) {
isLoading.postValue(false)
if (response.isSuccessful) {
val bodyResponse = response.body() ?: return
val listOfRestaurants = bodyResponse.restaurants
val restos = ArrayList<Restaurant>()
for (i in listOfRestaurants ) {
restos.add(i.restaurant)
}
if (start == 0) {
restaurants.postValue(restos)
} else {
restaurants.value?.let {
val newRestaurants = it
for (i in listOfRestaurants ) {
newRestaurants.add(i.restaurant)
}
restaurants.postValue(newRestaurants)
}
}
}
})
}
}
对象RestaurantClient{
val=MutableLiveData()
private val restaurantService=RefughtServiceGenerator.getInstance(RestaurantAPI::class.java)
有趣的搜索餐厅(查询:字符串、纬度:双精度、经度:双精度、起点:Int){
val call=restaurantService.searchRestaurants(
半径=2000,
query=query,
纬度=纬度,
经度=经度,
开始=开始,
计数=每页文档的数量
)
isLoading.value=true
排队(对象:Callback{
覆盖失效时的乐趣(调用:调用,t:可丢弃){
}
覆盖fun onResponse(调用:调用,响应:响应){
isLoading.postValue(false)
if(response.issucessful){
val bodyResponse=response.body()?:返回
val listOfRestaurants=bodyResponse.restaurants
val restos=ArrayList()
对于(我在员工名单中){
restos.add(即餐厅)
}
如果(开始==0){
餐厅。后价值(restos)
}否则{
休息