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;
}
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.