androidgridviewimageviewgoogle-cloud-firestoreglide-golang

How to clear GridView while working with Firestore?


The problem is that I can't refresh my gridView and when I make changes in Firestore, my gridView doesn't clear and just adds new values(images) from Firestore. I have tried lots of methods that I could find on "stackoverflow" but with no success. Maybe the problem is with ImageAdapter or with how I call addSnapshotListener, I really don't know. Right now I just want that I can refresh my gridView when data changes on Firestore, but in best case scenario I want that, when I get new values from Firestore, it only updates that part of gridView where was the image, and not the whole 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;
}

Solution

  • The 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

    If you want to hack it yourself, the QuerySnapshot has a property documentChanges that you can check for 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 - epecially the notifyItemXXX methods.