FirebaseRecyclerAdapter的populateViewHolder方法中的“addListenerForSingleValueEvent”会在Firebase参考下发生更改时被调用 [英] 'addListenerForSingleValueEvent' in populateViewHolder method of FirebaseRecyclerAdapter gets called whenever data changes under Firebase reference

查看:220
本文介绍了FirebaseRecyclerAdapter的populateViewHolder方法中的“addListenerForSingleValueEvent”会在Firebase参考下发生更改时被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序中使用 FirebaseRecyclerAdapter 并试图通过获取中的一些数据来填充它。populateViewHolder()方法,然后赋值给不同的参数。

这里是我的代码:

  private void attachRecyclerViewAdapter(){
Query lastFifty = aReference.child(requestID).limitToFirst(50);
mRecyclerViewAdapter = new FirebaseRecyclerAdapter< AModelClass,AModelClass.ViewHolder>(
AModelClass.class,R.layout.a_layout,AModelClass.ViewHolder.class,lastFifty){

@Override
protected void populateViewHolder(final AModelClass.ViewHolder viewHolder,AModelClass model,int position){
final String key = this.getRef(position).getKey();
aReference.child(requestID).addListenerForSingleValueEvent(new ValueEventListener(){
@Override $ b $ public void onDataChange(DataSnapshot dataSnapshot){$ b $ if(dataSnapshot.getValue()!= null ){
aReference.child(requestID).child(key).addListenerForSingleValueEvent(new ValueEventListener(){
@Override
public void onDataChange(DataSnapshot dataSnapshot){
$ b $ (dataSnapshot.getValue()!= null){

if(dataSnapshot.hasChild(pName)&&; dataSnapshot.hasChild(pUrl)&& dataSnapshot.hasChild (currentLat)&& amp; dataSnapshot.hasChild(currentLng)){
最终映射<字符串,字符串>映射=(映射<字符串,字符串>)dataSnapshot.g etValue();
pA = map.get(pName);
uidP = map.get(pUrl);
nP.add(map.get(pName));

cLatPlayers.add(map.get(currentLat)。trim());
cLngPlayers.add(map.get(currentLng)。trim());

viewHolder.setPNameT(pA);
viewHolder.setPicP(uidP);
viewHolder.setCurrentLatAU(String.valueOf(currentLtAU));
viewHolder.setCurrentLngAU(String.valueOf(currentLnAU));

addMarkers();

layout.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.INVISIBLE);
}

} else {
}

}
$ b $ @覆盖
public void onCancelled(DatabaseError databaseError ){

}
});

} else {
Toast.makeText(getBaseContext(),no data available yet,Toast.LENGTH_SHORT).show();



$ @覆盖
public void onCancelled(DatabaseError databaseError){

}
} );
}
};

mRecyclerViewAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver(){
@Override $ b $ public void onItemRangeRemoved(int positionStart,int itemCount){
}

@Override
public void onItemRangeInserted(int positionStart,int itemCount){
super.onItemRangeInserted(positionStart,itemCount);
}

@Override
public void onItemRangeChanged(int positionStart,int itemCount){
super.onItemRangeChanged(positionStart,itemCount);
}
});

aList.setAdapter(mRecyclerViewAdapter);

code
$ b $ p $ attachRecyclerViewAdapter()
放置在 onCreate()



以下是 aList 初始化在 onCreate()

  aList =(RecyclerView)findViewById R.id.aList); 
aList.setLayoutManager(nLinearLayoutManager);

以下是 onLocationChanged()方法: b>

  @Override 
public void onLocationChanged(Location location){
mCurrentLocation = location;
currentLtAU = mCurrentLocation.getLatitude();
currentLnAU = mCurrentLocation.getLongitude();

aReference.child(requestID).child(userID).child(currentLatUpdated).setValue(String.valueOf(currentLtAU));
aReference.child(requestID).child(userID).child(currentLngUpdated).setValue(String.valueOf(currentLnAU));



$ b $ p
$ b

当位置在相同的参考下改变时,它将更新后的lat和lng保存到数据库
$ b

LocationRequest 代码:

  protected void createLocationRequest(){
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(500);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(0);



$ b $ p
$ b

在这里一切正常,唯一的问题是引用的代码: aReference.child(requestID).child(key)或( aReference.child(requestID)>也许?)被一次又一次地调用(虽然它应该被调用一次,因为 addListenerForSingleValueEvent ),因此填充 nP cLatPlayers cLngPlayers 多次,还有 addMarkers() 方法在Map中被多次调用导致问题。



为什么会发生这种情况,我如何确保不会多次调用?


解决方案

那么我想出了一个非常简单而有效的解决方案。

我刚刚保存了更新的位置在数据库的不同引用中,以便每当它改变 aReference.child(requestID)下的 onDataChange()因此代码不会被一次又一次执行。



我将 onLocationChanged()中的代码从这:

  @Override 
public void onLocationChanged(Location location){
mCurrentLocation = location;
currentLtAU = mCurrentLocation.getLatitude();
currentLnAU = mCurrentLocation.getLongitude();

aReference.child(requestID).child(userID).child(currentLatUpdated).setValue(String.valueOf(currentLtAU));
aReference.child(requestID).child(userID).child(currentLngUpdated).setValue(String.valueOf(currentLnAU));



$ b $ p




  @Override 
public void onLocationChanged(Location location){
mCurrentLocation = location;
currentLtAU = mCurrentLocation.getLatitude();
currentLnAU = mCurrentLocation.getLongitude();

anotherReference.child(requestID).child(userID).child(currentLatUpdated).setValue(String.valueOf(currentLtAU));
anotherReference.child(requestID).child(userID).child(currentLngUpdated).setValue(String.valueOf(currentLnAU));
}

但是我仍然无法理解为什么 addListenerForSingleValueEvent ()每次监听数据更改,尽管它应该只监听一次数据更改。


I'm using FirebaseRecyclerAdapter in my app and trying to populate it by fetching some data inside it's populateViewHolder() method and then assigning values to different parameters.

Here's my code:

private void attachRecyclerViewAdapter() {
        Query lastFifty = aReference.child(requestID).limitToFirst(50);
        mRecyclerViewAdapter = new FirebaseRecyclerAdapter<AModelClass, AModelClass.ViewHolder>(
                AModelClass.class, R.layout.a_layout, AModelClass.ViewHolder.class, lastFifty) {

            @Override
            protected void populateViewHolder(final AModelClass.ViewHolder viewHolder, AModelClass model, int position) {
                final String key = this.getRef(position).getKey();
                aReference.child(requestID).addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        if (dataSnapshot.getValue() != null) {    
                            aReference.child(requestID).child(key).addListenerForSingleValueEvent(new ValueEventListener() {
                                @Override
                                public void onDataChange(DataSnapshot dataSnapshot) {

                                    if (dataSnapshot.getValue() != null) {

                                        if (dataSnapshot.hasChild("pName") && dataSnapshot.hasChild("pUrl") && dataSnapshot.hasChild("currentLat") && dataSnapshot.hasChild("currentLng")) {
                                            final Map<String, String> map = (Map<String, String>) dataSnapshot.getValue();
                                            pA = map.get("pName");
                                            uidP = map.get("pUrl");
                                            nP.add(map.get("pName"));

                                            cLatPlayers.add(map.get("currentLat").trim());
                                            cLngPlayers.add(map.get("currentLng").trim());

                                            viewHolder.setPNameT(pA);
                                            viewHolder.setPicP(uidP);
                                            viewHolder.setCurrentLatAU(String.valueOf(currentLtAU));
                                            viewHolder.setCurrentLngAU(String.valueOf(currentLnAU));

                                            addMarkers();

                                            layout.setVisibility(View.VISIBLE);
                                            progressBar.setVisibility(View.INVISIBLE);
                                        }

                                    } else {
                                    }

                                }

                                @Override
                                public void onCancelled(DatabaseError databaseError) {

                                }
                            });

                        } else {
                            Toast.makeText(getBaseContext(), "no data available yet", Toast.LENGTH_SHORT).show();
                        }

                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {

                    }
                });
            }
        };

        mRecyclerViewAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
            @Override
            public void onItemRangeRemoved(int positionStart, int itemCount) {
            }

            @Override
            public void onItemRangeInserted(int positionStart, int itemCount) {
                super.onItemRangeInserted(positionStart, itemCount);
            }

            @Override
            public void onItemRangeChanged(int positionStart, int itemCount) {
                super.onItemRangeChanged(positionStart, itemCount);
            }
        });

        aList.setAdapter(mRecyclerViewAdapter);
    }

attachRecyclerViewAdapter() is placed in onCreate().

Here's aList initialisation in onCreate():

aList = (RecyclerView) findViewById(R.id.aList);
aList.setLayoutManager(nLinearLayoutManager);

Here's onLocationChanged() method:

@Override
public void onLocationChanged(Location location) {
        mCurrentLocation = location;
        currentLtAU = mCurrentLocation.getLatitude();
        currentLnAU = mCurrentLocation.getLongitude();

        aReference.child(requestID).child(userID).child("currentLatUpdated").setValue(String.valueOf(currentLtAU));
        aReference.child(requestID).child(userID).child("currentLngUpdated").setValue(String.valueOf(currentLnAU));        
}

which saves updated lat and lng to database whenever location is changed under the same reference from where data is getting retrieved above.

The LocationRequest code:

protected void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(1000);
        mLocationRequest.setFastestInterval(500);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setSmallestDisplacement(0);
}

Everything is working just fine here, the only problem is that the code under reference: aReference.child(requestID).child(key) or (aReference.child(requestID) maybe?) is getting called again and again (though it is supposed to be called just once because of addListenerForSingleValueEvent), thus filling nP, cLatPlayers, cLngPlayers multiple times and also the addMarkers() method is getting called multiple times causing problem in the Map.

Why is this happening and How can I make sure that this doesn't gets called multiple times?

解决方案

Well I came up with a very simple yet effective solution.

I just saved the updated locations at a different reference in database so that whenever it changes the onDataChange() under aReference.child(requestID) is not called and thus the code does not gets executed again and again.

I changed the code under onLocationChanged() from this:

@Override
public void onLocationChanged(Location location) {
        mCurrentLocation = location;
        currentLtAU = mCurrentLocation.getLatitude();
        currentLnAU = mCurrentLocation.getLongitude();

        aReference.child(requestID).child(userID).child("currentLatUpdated").setValue(String.valueOf(currentLtAU));
        aReference.child(requestID).child(userID).child("currentLngUpdated").setValue(String.valueOf(currentLnAU));        
} 

to this:

@Override
public void onLocationChanged(Location location) {
        mCurrentLocation = location;
        currentLtAU = mCurrentLocation.getLatitude();
        currentLnAU = mCurrentLocation.getLongitude();

        anotherReference.child(requestID).child(userID).child("currentLatUpdated").setValue(String.valueOf(currentLtAU));
        anotherReference.child(requestID).child(userID).child("currentLngUpdated").setValue(String.valueOf(currentLnAU));        
}

But I'm still unable to understand why addListenerForSingleValueEvent() listens for data changes every time though it is supposed to listen data changes just once.

这篇关于FirebaseRecyclerAdapter的populateViewHolder方法中的“addListenerForSingleValueEvent”会在Firebase参考下发生更改时被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆