如何在使用 Firestore 时清除 GridView?

How to clear GridView while working with Firestore?

问题是我无法刷新我的 gridView,当我在 Firestore 中进行更改时,我的 gridView 不清除,只是从 Firestore 添加新值(图像)。我尝试了很多可以在 "Whosebug" 上找到的方法,但都没有成功。也许问题出在 ImageAdapter 或我如何调用 addSnapshotListener,我真的不知道。现在我只想在 Firestore 上的数据更改时刷新我的 gridView,但在最好的情况下我希望,当我从 Firestore 获取新值时,它只更新 gridView 的那一部分是图像,而不是整个 gridView.

public class MainActivity extends AppCompatActivity {

private FirebaseFirestore db;
private ArrayList<Items> arrayList;
private ImageAdapter imageAdapter;
private GridView gridView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    gridView = findViewById(R.id.gridViewList);
    db = FirebaseFirestore.getInstance();
    arrayList = new ArrayList<>();
    //arrayList.clear();

    getUrls();

    imageAdapter = new ImageAdapter(MainActivity.this, arrayList);
    gridView.setAdapter(imageAdapter);

}

private void getUrls(){
    gridView.setAdapter(null);
    db.collection("images").addSnapshotListener(new EventListener<QuerySnapshot>() {
        @Override
        public void onEvent(QuerySnapshot value, FirebaseFirestoreException e) {
            if (e != null){
                Toast.makeText(getApplicationContext(), "No images returned", Toast.LENGTH_SHORT).show();
                return;
            }
            for (DocumentSnapshot document : value){
                refresh();
                if (document.get("imageUrl") != null){
                    arrayList.add(new Items(document.get("imageUrl").toString()));
                    refresh();
                }
            }
        }
    });
}


public void refresh() {
    new Handler(Looper.getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            imageAdapter.notifyDataSetChanged();
            gridView.invalidate();
        }
    });
}

public class ImageAdapter extends BaseAdapter {

private ImageView imageView;
private Context context;
private LayoutInflater inflater;
private ArrayList<Items> list;

public ImageAdapter(Context context, ArrayList<Items> list){
    this.context = context;
    this.list = list;
}

@Override
public int getCount() {
    return list.size();
}

@Override
public Object getItem(int position) {
    return position;
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null){
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.image_layout, parent, false);
        imageView = convertView.findViewById(R.id.singleImageView);
    }

    /** https://futurestud.io/tutorials/glide-caching-basics */
    Glide.with(context).load(list.get(position).getImageUrl()).apply(RequestOptions.skipMemoryCacheOf(true).centerCrop()).into(imageView);
    return convertView;
}

FirebaseUI-Android/Firestore project has an adapter that does what you want. This does the heavy lifting of managing a RecyclerView for you. In order to have a layout like in GridView, you can create an instance of GridLayoutManager in onCreate and pass that to RecyclerView.setLayoutManager

如果您想自己破解它,QuerySnapshot 有一个 属性 documentChanges,您可以检查 REMOVED - cf. View changes between snapshots. To get an idea of how it would be implemented with a GridView you can look at the source code of RecyclerView.Adatper - 特别是 notifyItemXXX 方法。