Store Retrieve Images in Firebase Database using Android Studio and Display in RecyclerView, GridView, and Staggered Layout

Table of Contents

What is Firebase Realtime Database?

Firebase is a service to applications, it provides hosting, NoSQL storage, real-time databases, social authentication, notification, and other services.

GridView

GridView is a widget in Android Studio that displays items in a two-dimensional grid. Each item is represented by a View object, which can be a text view, image view, or any other type of view. GridView is often used to display images, but it can be used to display any type of view.

Staggered Layout

Staggered Layout is a type of layout manager in Android Studio that is used to display items in a staggered grid or masonry style layout. Unlike GridView or RecyclerView’s GridLayoutManager, Staggered Layout Manager allows for items of different sizes to be displayed in the same row or column, resulting in a more dynamic and visually appealing layout. In a staggered layout, the items are positioned based on their content and not on a fixed column or row. This layout is useful when you want to display items in a grid-like layout, but the items are not of the same size or when you want to create an interesting visual effect. To use Staggered Layout in your Android Studio project, you can create a new StaggeredGridLayoutManager object and set it to your RecyclerView.

Step-by-Step Implementation

Step 1: Open Android Studio, Click New Project and Choose Empty Activity.

Step 2:colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="lavender">#8692f7</color>
</resources>

themes.xml

<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.UploadRetrieveImage" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/lavender</item>
<item name="colorPrimaryVariant">@color/lavender</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
<style name="Theme.UploadActivity" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/lavender</item>
<item name="colorPrimaryVariant">@color/lavender</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

lavender_border.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="2dp"
android:color="@color/lavender"/>
<corners
android:radius="30dp"/>
</shape>

AndroidManifest.xml

<activity
android:name=".UploadActivity"
android:exported="false"
android:theme="@style/Theme.UploadActivity"/>

Gradle: Module

implementation 'com.github.bumptech.glide:glide:4.14.2'
annotationProcessor 'com.github.bumptech.glide:compiler:4.14.2'
implementation 'com.makeramen:roundedimageview:2.3.0'

Upload Images

activity_upload.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/uploadbkg"
tools:context=".UploadActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@drawable/lavender_border"
android:padding="20dp"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"
android:layout_marginTop="230dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="200dp"
android:src="@drawable/uploadimg"
android:id="@+id/uploadImage"
android:layout_marginTop="20dp"
android:scaleType="fitXY"/>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/progressBar"
android:layout_gravity="center"
android:indeterminateTint="@color/lavender"
android:visibility="invisible"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="200dp"
android:orientation="horizontal">
<EditText
android:layout_width="0dp"
android:layout_height="60dp"
android:id="@+id/uploadCaption"
android:layout_weight="0.6"
android:background="@drawable/lavender_border"
android:padding="16dp"
android:hint="Add a caption..."/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/uploadButton"
android:layout_marginStart="10dp"
android:backgroundTint="@color/lavender"
android:src="@drawable/baseline_send_24"
app:tint = "@color/white"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>

DataClass.java

package com.example.uploadretrieveimage;
public class DataClass {
private String imageURL, caption;
public DataClass(){
}
public String getImageURL() {
return imageURL;
}
public void setImageURL(String imageURL) {
this.imageURL = imageURL;
}
public String getCaption() {
return caption;
}
public void setCaption(String caption) {
this.caption = caption;
}
public DataClass(String imageURL, String caption) {
this.imageURL = imageURL;
this.caption = caption;
}
}

UploadActivity.java

Related Article
package com.example.uploadretrieveimage;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.webkit.MimeTypeMap;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.OnProgressListener;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;
public class UploadActivity extends AppCompatActivity {
private FloatingActionButton uploadButton;
private ImageView uploadImage;
EditText uploadCaption;
ProgressBar progressBar;
private Uri imageUri;
final private DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Images");
final private StorageReference storageReference = FirebaseStorage.getInstance().getReference();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_upload);
uploadButton = findViewById(R.id.uploadButton);
uploadCaption = findViewById(R.id.uploadCaption);
uploadImage = findViewById(R.id.uploadImage);
progressBar = findViewById(R.id.progressBar);
progressBar.setVisibility(View.INVISIBLE);
ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK){
Intent data = result.getData();
imageUri = data.getData();
uploadImage.setImageURI(imageUri);
} else {
Toast.makeText(UploadActivity.this, "No Image Selected", Toast.LENGTH_SHORT).show();
}
}
}
);
uploadImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent photoPicker = new Intent();
photoPicker.setAction(Intent.ACTION_GET_CONTENT);
photoPicker.setType("image/*");
activityResultLauncher.launch(photoPicker);
}
});
uploadButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (imageUri != null){
uploadToFirebase(imageUri);
} else {
Toast.makeText(UploadActivity.this, "Please select image", Toast.LENGTH_SHORT).show();
}
}
});
}
//Outside onCreate
private void uploadToFirebase(Uri uri){
String caption = uploadCaption.getText().toString();
final StorageReference imageReference = storageReference.child(System.currentTimeMillis() + "." + getFileExtension(uri));
imageReference.putFile(uri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
imageReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
@Override
public void onSuccess(Uri uri) {
DataClass dataClass = new DataClass(uri.toString(), caption);
String key = databaseReference.push().getKey();
databaseReference.child(key).setValue(dataClass);
progressBar.setVisibility(View.INVISIBLE);
Toast.makeText(UploadActivity.this, "Uploaded", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(UploadActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
});
}
}).addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
@Override
public void onProgress(@NonNull UploadTask.TaskSnapshot snapshot) {
progressBar.setVisibility(View.VISIBLE);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
progressBar.setVisibility(View.INVISIBLE);
Toast.makeText(UploadActivity.this, "Failed", Toast.LENGTH_SHORT).show();
}
});
}
private String getFileExtension(Uri fileUri){
ContentResolver contentResolver = getContentResolver();
MimeTypeMap mime = MimeTypeMap.getSingleton();
return mime.getExtensionFromMimeType(contentResolver.getType(fileUri));
}
}

Retrieve Images – RecyclerView

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_margin="40dp"
android:backgroundTint="@color/lavender"
app:tint = "@color/white"
android:src="@drawable/baseline_add_24" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>

recycler_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:layout_marginTop="20dp"
app:cardCornerRadius="20dp"
android:elevation="10dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recyclerImage"
android:src="@drawable/uploadimg"
android:scaleType="centerCrop"/>
</androidx.cardview.widget.CardView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="caption"
android:textSize="18sp"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="10dp"
android:textColor="@color/lavender"
android:id="@+id/recyclerCaption"/>
</LinearLayout>

MyAdapter.java

package com.example.storeretrieveimagepractice;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private ArrayList<DataClass> dataList;
private Context context;
public MyAdapter(Context context, ArrayList<DataClass> dataList) {
this.context = context;
this.dataList = dataList;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.recycler_item, parent, false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
Glide.with(context).load(dataList.get(position).getImageURL()).into(holder.recyclerImage);
holder.recyclerCaption.setText(dataList.get(position).getCaption());
}
@Override
public int getItemCount() {
return dataList.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
ImageView recyclerImage;
TextView recyclerCaption;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
recyclerImage = itemView.findViewById(R.id.recyclerImage);
recyclerCaption = itemView.findViewById(R.id.recyclerCaption);
}
}
}

MainActivity.java

package com.example.storeretrieveimagepractice;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
FloatingActionButton fab;
private RecyclerView recyclerView;
private ArrayList<DataClass> dataList;
private MyAdapter adapter;
final private DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Images");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fab = findViewById(R.id.fab);
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
dataList = new ArrayList<>();
adapter = new MyAdapter(this, dataList);
recyclerView.setAdapter(adapter);
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
DataClass dataClass = dataSnapshot.getValue(DataClass.class);
dataList.add(dataClass);
}
adapter.notifyDataSetChanged();
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, UploadActivity.class);
startActivity(intent);
finish();
}
});
}
}

Retrieve Images – GridView

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_margin="40dp"
android:backgroundTint="@color/lavender"
app:tint = "@color/white"
android:src="@drawable/baseline_add_24" />
<GridView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/gridView"
android:numColumns="2"/>
</RelativeLayout>

grid_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:gravity="center">
<androidx.cardview.widget.CardView
android:layout_width="150dp"
android:layout_height="150dp"
app:cardElevation="10dp"
app:cardCornerRadius="20dp">
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:scaleType="centerCrop"
android:id="@+id/gridImage"/>
</androidx.cardview.widget.CardView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/gridCaption"
android:text="Captions"
android:textSize="20sp"
android:gravity="center"
android:textColor="@color/lavender"
android:layout_marginTop="8dp"/>
</LinearLayout>

MainActivity.java

package com.example.storeretrieveimagepractice;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.GridView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
FloatingActionButton fab;
private GridView gridView;
private ArrayList<DataClass> dataList;
private MyAdapter adapter;
final private DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Images");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fab = findViewById(R.id.fab);
gridView = findViewById(R.id.gridView);
dataList = new ArrayList<>();
adapter = new MyAdapter(this, dataList);
gridView.setAdapter(adapter);
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
DataClass dataClass = dataSnapshot.getValue(DataClass.class);
dataList.add(dataClass);
}
adapter.notifyDataSetChanged();
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, UploadActivity.class);
startActivity(intent);
finish();
}
});
}
}

MyAdapter.java

package com.example.storeretrieveimagepractice;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
public class MyAdapter extends BaseAdapter {
private ArrayList<DataClass> dataList;
private Context context;
LayoutInflater layoutInflater;
public MyAdapter(Context context, ArrayList<DataClass> dataList) {
this.context = context;
this.dataList = dataList;
}
@Override
public int getCount() {
return dataList.size();
}
@Override
public Object getItem(int i) {
return null;
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
if (layoutInflater == null){
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
if (view == null){
view = layoutInflater.inflate(R.layout.grid_item, null);
}
ImageView gridImage = view.findViewById(R.id.gridImage);
TextView gridCaption = view.findViewById(R.id.gridCaption);
Glide.with(context).load(dataList.get(i).getImageURL()).into(gridImage);
gridCaption.setText(dataList.get(i).getCaption());
return view;
}
}

Retrieve Images – Staggered Layout

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/fab"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_margin="40dp"
android:backgroundTint="@color/lavender"
android:src="@drawable/baseline_add_24"
app:tint = "@color/white"/>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recyclerView"
android:paddingStart="0dp"
android:paddingEnd="15dp"
android:paddingBottom="15dp"/>
</RelativeLayout>

staggere_item.xml

<?xml version="1.0" encoding="utf-8"?>
<com.makeramen.roundedimageview.RoundedImageView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/staggeredImages"
android:layout_marginStart="15dp"
android:layout_marginTop="15dp"
app:riv_corner_radius="12dp"
android:adjustViewBounds="true"/>

MainActivity.java

package com.example.uploadretrieveimage;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.GridView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
ArrayList<DataClass> dataList;
MyAdapter adapter;
final private DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Images");
FloatingActionButton fab;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fab = findViewById(R.id.fab);
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
dataList = new ArrayList<>();
adapter = new MyAdapter(dataList, this);
recyclerView.setAdapter(adapter);
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot: snapshot.getChildren()){
DataClass dataClass = dataSnapshot.getValue(DataClass.class);
dataList.add(dataClass);
}
adapter.notifyDataSetChanged();
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, UploadActivity.class);
startActivity(intent);
finish();
}
});
}
}

MyAdapter.java

package com.example.uploadretrieveimage;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.bumptech.glide.Glide;
import com.makeramen.roundedimageview.RoundedImageView;
import java.util.ArrayList;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
ArrayList<DataClass> dataList;
Context context;
public MyAdapter(ArrayList<DataClass> dataList, Context context) {
this.dataList = dataList;
this.context = context;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.staggered_item, parent, false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
Glide.with(context).load(dataList.get(position).getImageURL()).into(holder.staggeredImages);
}
@Override
public int getItemCount() {
return dataList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder{
RoundedImageView staggeredImages;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
staggeredImages = itemView.findViewById(R.id.staggeredImages);
}
}
}

Output

upload retrieve images firebase

AK Bonus Points