Firebase ValueEventListener在RecyclerView

时间:2018-01-31 13:03:04

标签: android firebase firebase-realtime-database firebase-storage

由于每次ValueEventListener中的数据更新时都会触发Firebase Database,因此在RecyclerView显示时完成新上传时也会调用Upload。我这样做的方式现在会导致重复输入,因为mUploads List中的ArrayList个对象已经是。上传完成后,将再次查询整个数据库,并将所有项目添加到已存在的Arraylist我不知道如何解决此问题。每次触发ValueEventListener时我应该创建一个新的ValueEventListener还是需要一个完全不同的回调? 另外,mAdapter.notifyItemRemoved会干扰我的ValueEventListener来电,因为public class ImagesActivity extends AppCompatActivity implements ImageAdapter.OnItemClickListener { private RecyclerView mRecyclerView; private ImageAdapter mAdapter; private ProgressBar mProgressCircle; private DatabaseReference mDatabaseRef; private FirebaseStorage mStorage; private List<Upload> mUploads; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_show_images); mUploads = new ArrayList<>(); mRecyclerView = findViewById(R.id.recycler_view); mRecyclerView.setHasFixedSize(true); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); mProgressCircle = findViewById(R.id.progress_circle); mDatabaseRef = FirebaseDatabase.getInstance().getReference("uploads"); mStorage = FirebaseStorage.getInstance(); mDatabaseRef.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) { Upload upload = postSnapshot.getValue(Upload.class); upload.setKey(postSnapshot.getKey()); mUploads.add(upload); } mAdapter = new ImageAdapter(ImagesActivity.this, mUploads); mRecyclerView.setAdapter(mAdapter); mAdapter.setOnItemClickListener(ImagesActivity.this); mProgressCircle.setVisibility(View.INVISIBLE); } @Override public void onCancelled(DatabaseError databaseError) { Toast.makeText(ImagesActivity.this, databaseError.getMessage(), Toast.LENGTH_LONG).show(); mProgressCircle.setVisibility(View.INVISIBLE); } }); } @Override public void onDeleteClick(final int position) { Upload selectedItem = mUploads.get(position); final String selectedKey = selectedItem.getKey(); StorageReference imageRef = mStorage.getReferenceFromUrl(selectedItem.getImageUrl()); imageRef.delete().addOnSuccessListener(new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { mDatabaseRef.child(selectedKey).removeValue(); mUploads.remove(position); mAdapter.notifyItemRemoved(position); } }); } } 会在我删除内容后立即触发。

function MakeMargin(props) {
    return theme.spacing[props]
}

5 个答案:

答案 0 :(得分:3)

addValueEventListener添加数据之前

清除 mDatabaseRef.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { mUploads.clear(); //change here for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) { Upload upload = postSnapshot.getValue(Upload.class); upload.setKey(postSnapshot.getKey()); mUploads.add(upload); } mAdapter = new ImageAdapter(ImagesActivity.this, mUploads); mRecyclerView.setAdapter(mAdapter); mAdapter.setOnItemClickListener(ImagesActivity.this); mProgressCircle.setVisibility(View.INVISIBLE); }

console.log(object)

答案 1 :(得分:2)

试试这个

在addValueEventListener之前清除arraylist mUploads.clear(),如下所示

mUploads.clear();

答案 2 :(得分:2)

而不是使用ValueEventListener考虑附加ChildEventListener。为添加,更改或删除的各个子节点触发此类型的侦听器。

当您最初附加ChildEventListener时,将为侦听器匹配的每个子项调用其onChildAdded。然后,当您稍后将子节点添加到数据库时,将仅使用现有子再次调用onChildAdded。这使得更新UI变得非常容易,只需将新子项添加到适配器即可。

ChildEventListener也有一个onChildChanged事件,当特定孩子更改时会触发该事件。在这里,该方法仅使用现有子项触发,再次使得更新适配器中的该子项变得容易。

有关此类侦听器的详情,请参阅Firebase文档中的listen for child events

答案 3 :(得分:1)

您可以使用addListenerForSingleValueEvent()这将读取一次数据,如果您想刷新数据,可以再次调用,以获取更多信息 Firebase - read data once

答案 4 :(得分:1)

我建议您使用addListenerForSingleValueEvent以便一次性提取数据,最后添加addChildEventListener并覆盖onChildAdded,这样也会获取新的添加项,我认为这样比清除列表和重新充气Recyclerview更好

结帐代码

mDatabaseRef.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {

        for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
            Upload upload = postSnapshot.getValue(Upload.class);
            upload.setKey(postSnapshot.getKey());

            mUploads.add(upload);
        }

        mAdapter = new ImageAdapter(ImagesActivity.this, mUploads);
        mRecyclerView.setAdapter(mAdapter);
        mAdapter.setOnItemClickListener(ImagesActivity.this);
        mProgressCircle.setVisibility(View.INVISIBLE);

        mDatabaseRef.addChildEventListener(new ChildEventListener(){
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
                Upload upload = postSnapshot.getValue(Upload.class);
                upload.setKey(postSnapshot.getKey());
                mUploads.add(upload);
            }

        })
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        Toast.makeText(ImagesActivity.this, databaseError.getMessage(), Toast.LENGTH_LONG).show();
        mProgressCircle.setVisibility(View.INVISIBLE);
    }
});