Best Way to Download Images and Show in Data Adapter in Android

andorid-recycler-view

Downloading images and displaying them efficiently in an Android application is a common requirement, especially for apps dealing with media, social networks, or e-commerce. Utilizing third-party HTTP client libraries can greatly simplify this process. In this blog, we will explore the best practices for downloading images and showing them in a data adapter using Retrofit and Glide, two popular libraries in Android development.

Introduction

When building Android applications that need to download and display images, handling the network operations efficiently and ensuring smooth user experience is crucial. Retrofit is a powerful type-safe HTTP client for Android, while Glide is a fast and efficient image loading library. Together, they provide an excellent solution for this task.

Setting Up Your Project

First, ensure that your project includes the necessary dependencies for Retrofit and Glide. build.gradle (Module: app)
dependencies {
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation 'com.github.bumptech.glide:glide:4.12.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
}

Creating the Retrofit Client

Retrofit is used to define and manage network requests in a clean and straightforward way.

API Interface

Create an interface to define your API endpoints.
public interface ApiService {
    @GET("photos")
    Call<List<Photo>> getPhotos();
}

Retrofit Instance

Create a singleton instance of Retrofit to manage network requests.
public class ApiClient {
    private static final String BASE_URL = "https://api.example.com/";
    private static Retrofit retrofit = null;

    public static Retrofit getClient() {
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }
}

Creating the Data Model

Define a data model to map the JSON response.
public class Photo {
    @SerializedName("id")
    private int id;

    @SerializedName("title")
    private String title;

    @SerializedName("url")
    private String url;

    // Getters and Setters
}

Setting Up the RecyclerView Adapter

Create an adapter for your RecyclerView to bind the photo data to the UI components.

PhotoAdapter.java

public class PhotoAdapter extends RecyclerView.Adapter<PhotoAdapter.PhotoViewHolder> {
    private List<Photo> photos;
    private Context context;

    public PhotoAdapter(Context context, List<Photo> photos) {
        this.context = context;
        this.photos = photos;
    }

    @Override
    public PhotoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.photo_item, parent, false);
        return new PhotoViewHolder(view);
    }

    @Override
    public void onBindViewHolder(PhotoViewHolder holder, int position) {
        Photo photo = photos.get(position);
        holder.title.setText(photo.getTitle());
        Glide.with(context)
                .load(photo.getUrl())
                .placeholder(R.drawable.placeholder)
                .into(holder.imageView);
    }

    @Override
    public int getItemCount() {
        return photos.size();
    }

    public static class PhotoViewHolder extends RecyclerView.ViewHolder {
        ImageView imageView;
        TextView title;

        public PhotoViewHolder(View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.photo_image);
            title = itemView.findViewById(R.id.photo_title);
        }
    }
}

Creating the Layout Files

Define the layout for each photo item and the main activity layout.

res/layout/photo_item.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="8dp">

    <ImageView
        android:id="@+id/photo_image"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:scaleType="centerCrop" />

    <TextView
        android:id="@+id/photo_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="4dp"
        android:textSize="16sp" />
</LinearLayout>

res/layout/activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="8dp"
        android:scrollbars="vertical" />
</RelativeLayout>

Fetching Data and Displaying in RecyclerView

In your main activity, fetch the photo data from the API and set up the RecyclerView.

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private PhotoAdapter photoAdapter;
    private List<Photo> photoList;

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

        recyclerView = findViewById(R.id.recycler_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        photoList = new ArrayList<>();
        photoAdapter = new PhotoAdapter(this, photoList);
        recyclerView.setAdapter(photoAdapter);

        fetchPhotos();
    }

    private void fetchPhotos() {
        ApiService apiService = ApiClient.getClient().create(ApiService.class);
        Call<List<Photo>> call = apiService.getPhotos();

        call.enqueue(new Callback<List<Photo>>() {
            @Override
            public void onResponse(Call<List<Photo>> call, Response<List<Photo>> response) {
                if (response.isSuccessful() && response.body() != null) {
                    photoList.addAll(response.body());
                    photoAdapter.notifyDataSetChanged();
                }
            }

            @Override
            public void onFailure(Call<List<Photo>> call, Throwable t) {
                Toast.makeText(MainActivity.this, "Failed to load photos", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

 

Need Debugging? – Try RobotQA and Start Debugging on Real Devices. Download Plugin

 

Conclusion

By using Retrofit and Glide together, you can efficiently download images and display them in a RecyclerView. Retrofit handles the network operations, while Glide handles image loading and caching. This combination ensures that your application is responsive and provides a smooth user experience. Following these best practices will help you create a more robust and maintainable Android application.
Tagged:

Related Posts