Native Mobile App Development With Java

Android MVP Retrofit Example

15-Sep-2024

How to implement the MVP pattern with Retrofit for API calls in Android Studio using Java

 We Get Data From https://www.themealdb.com/api/json/v1/1/categories.php this url



{
"categories": [
{
"idCategory": "1",
"strCategory": "Beef",
"strCategoryThumb": "https://www.themealdb.com/images/category/beef.png",
"strCategoryDescription": "Beef is the culinary name for meat from cattle, particularly skeletal muscle. Humans have been eating beef since prehistoric times.[1] Beef is a source of high-quality protein and essential nutrients.[2]"
},
{
"idCategory": "2",
"strCategory": "Chicken",
"strCategoryThumb": "https://www.themealdb.com/images/category/chicken.png",
"strCategoryDescription": "Chicken is a type of domesticated fowl, a subspecies of the red junglefowl. It is one of the most common and widespread domestic animals, with a total population of more than 19 billion as of 2011.[1] Humans commonly keep chickens as a source of food (consuming both their meat and eggs) and, more rarely, as pets."
},
{
"idCategory": "3",
"strCategory": "Dessert",
"strCategoryThumb": "https://www.themealdb.com/images/category/dessert.png",
"strCategoryDescription": "Dessert is a course that concludes a meal. The course usually consists of sweet foods, such as confections dishes or fruit, and possibly a beverage such as dessert wine or liqueur, however in the United States it may include coffee, cheeses, nuts, or other savory items regarded as a separate course elsewhere. In some parts of the world, such as much of central and western Africa, and most parts of China, there is no tradition of a dessert course to conclude a meal.\r\n\r\nThe term dessert can apply to many confections, such as biscuits, cakes, cookies, custards, gelatins, ice creams, pastries, pies, puddings, and sweet soups, and tarts. Fruit is also commonly found in dessert courses because of its naturally occurring sweetness. Some cultures sweeten foods that are more commonly savory to create desserts."
},
{
"idCategory": "4",
"strCategory": "Lamb",
"strCategoryThumb": "https://www.themealdb.com/images/category/lamb.png",
"strCategoryDescription": "Lamb, hogget, and mutton are the meat of domestic sheep (species Ovis aries) at different ages.\r\n\r\nA sheep in its first year is called a lamb, and its meat is also called lamb. The meat of a juvenile sheep older than one year is hogget; outside the USA this is also a term for the living animal. The meat of an adult sheep is mutton, a term only used for the meat, not the living animals. The term mutton is almost always used to refer to goat meat in the Indian subcontinent.\r\n\r\n"
},
{
"idCategory": "5",
"strCategory": "Miscellaneous",
"strCategoryThumb": "https://www.themealdb.com/images/category/miscellaneous.png",
"strCategoryDescription": "General foods that don't fit into another category"
},
{
"idCategory": "6",
"strCategory": "Pasta",
"strCategoryThumb": "https://www.themealdb.com/images/category/pasta.png",
"strCategoryDescription": "Pasta is a staple food of traditional Italian cuisine, with the first reference dating to 1154 in Sicily.\r\n\r\nAlso commonly used to refer to the variety of pasta dishes, pasta is typically a noodle made from an unleavened dough of a durum wheat flour mixed with water or eggs and formed into sheets or various shapes, then cooked by boiling or baking. As an alternative for those wanting a different taste, or who need to avoid products containing gluten, some pastas can be made using rice flour in place of wheat.[3][4] Pastas may be divided into two broad categories, dried (pasta secca) and fresh (pasta fresca)."
},
{
"idCategory": "7",
"strCategory": "Pork",
"strCategoryThumb": "https://www.themealdb.com/images/category/pork.png",
"strCategoryDescription": "Pork is the culinary name for meat from a domestic pig (Sus scrofa domesticus). It is the most commonly consumed meat worldwide,[1] with evidence of pig husbandry dating back to 5000 BC. Pork is eaten both freshly cooked and preserved. Curing extends the shelf life of the pork products. Ham, smoked pork, gammon, bacon and sausage are examples of preserved pork. Charcuterie is the branch of cooking devoted to prepared meat products, many from pork.\r\n\r\nPork is the most popular meat in Eastern and Southeastern Asia, and is also very common in the Western world, especially in Central Europe. It is highly prized in Asian cuisines for its fat content and pleasant texture. Consumption of pork is forbidden by Jewish and Muslim dietary law, a taboo that is deeply rooted in tradition, with several suggested possible causes. The sale of pork is limited in Israel and illegal in certain Muslim countries."
},
{
"idCategory": "8",
"strCategory": "Seafood",
"strCategoryThumb": "https://www.themealdb.com/images/category/seafood.png",
"strCategoryDescription": "Seafood is any form of sea life regarded as food by humans. Seafood prominently includes fish and shellfish. Shellfish include various species of molluscs, crustaceans, and echinoderms. Historically, sea mammals such as whales and dolphins have been consumed as food, though that happens to a lesser extent in modern times. Edible sea plants, such as some seaweeds and microalgae, are widely eaten as seafood around the world, especially in Asia (see the category of sea vegetables). In North America, although not generally in the United Kingdom, the term \"seafood\" is extended to fresh water organisms eaten by humans, so all edible aquatic life may be referred to as seafood. For the sake of completeness, this article includes all edible aquatic life."
}
]
}


1/  Create A New Project and add Libarary.




dependencies {

implementation libs.appcompat
implementation libs.material
implementation libs.activity
implementation libs.constraintlayout
testImplementation libs.junit
androidTestImplementation libs.ext.junit
androidTestImplementation libs.espresso.core

implementation "com.squareup.retrofit2:converter-gson:2.8.1" //Add Library for retrofit here
implementation "com.squareup.retrofit2:retrofit:2.9.0"
  implementation "com.github.bumptech.glide:glide:4.11.0" //Add Library for Image
annotationProcessor "com.github.bumptech.glide:compiler:4.11.0"

}



2/  Create a Model Class CategoryData.class





package com.example.mvpretrofit.models;

public class CategoryData {
String idCategory;
String strCategory;
String strCategoryThumb;
String strCategoryDescription;


public CategoryData(String idCategory, String strCategory, String strCategoryThumb, String strCategoryDescription) {
this.idCategory = idCategory;
this.strCategory = strCategory;
this.strCategoryThumb = strCategoryThumb;
this.strCategoryDescription = strCategoryDescription;


}

public String getIdCategory() {
return idCategory;
}

public void setIdCategory(String idCategory) {
this.idCategory = idCategory;
}

public String getStrCategory() {
return strCategory;
}

public void setStrCategory(String strCategory) {
this.strCategory = strCategory;
}

public String getStrCategoryThumb() {
return strCategoryThumb;
}

public void setStrCategoryThumb(String strCategoryThumb) {
this.strCategoryThumb = strCategoryThumb;
}

public String getStrCategoryDescription() {
return strCategoryDescription;
}

public void setStrCategoryDescription(String strCategoryDescription) {
this.strCategoryDescription = strCategoryDescription;
}
}



3/  Create a class CategoryResponse.class



package com.example.mvpretrofit.models;

import java.util.ArrayList;

public class CategoryResponse {

ArrayList <CategoryData> categories;

public CategoryResponse(ArrayList<CategoryData> categories) {
this.categories = categories;
}

public ArrayList<CategoryData> getCategories() {
return categories;
}

public void setCategories(ArrayList<CategoryData> categories) {
this.categories = categories;
}
}


4/  Create a interface  RetrofitAPI


package com.example.mvpretrofit.api_service;
import com.example.mvpretrofit.models.CategoryResponse;

import retrofit2.Call;
import retrofit2.http.GET;

public interface RetrofitAPI {

@GET("1/categories.php")
Call<CategoryResponse> getAllCategory();


}





5/  Create a class  APIService.class


package com.example.mvpretrofit.api_service;

import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class APIService {

private Retrofit retrofit = null;
public RetrofitAPI getAPI() {
String BASE_URL = "https://www.themealdb.com/api/json/v1/";

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

return retrofit.create(RetrofitAPI.class);
}
}




6/  Create a interface MainView .


package com.example.mvpretrofit.views;

import com.example.mvpretrofit.models.CategoryData;

import java.util.ArrayList;


public interface MainView {
void categoryList(ArrayList<CategoryData> categoryList);
}




7/  Create a class MainPresenter.




package com.example.mvpretrofit.presenter;

import com.example.mvpretrofit.views.MainView;
import com.example.mvpretrofit.api_service.APIService;
import com.example.mvpretrofit.models.CategoryResponse;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class MainPresenter {

private MainView mainView;
private APIService apiService;


public MainPresenter(MainView view) {
this.mainView = view;

if (this.apiService == null) {
this.apiService = new APIService();
}
}


public void getCategory() {
apiService
.getAPI()
.getAllCategory()
.enqueue(new Callback<CategoryResponse>() {
@Override
public void onResponse(Call<CategoryResponse> call, Response<CategoryResponse> response) {
mainView.categoryList(response.body().getCategories());
}

@Override
public void onFailure(Call<CategoryResponse> call, Throwable t) {

}
});

}
}




8/  Create a Layout  category_card_lay.xml.



<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:id="@+id/cat_name"
android:layout_width="match_parent"
android:padding="20dp"
android:textSize="20dp"
android:layout_height="wrap_content"
android:text="Name" />
</RelativeLayout>



9/  Create a Adapter Class CategoryAdapter.




package com.example.mvpretrofit.adpter;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.example.mvpretrofit.R;
import com.example.mvpretrofit.models.CategoryData;

import java.util.ArrayList;

public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.MyViewHolder>{

ArrayList<CategoryData> categoryData;
public CategoryAdapter(ArrayList<CategoryData> categoryData){

this.categoryData=categoryData;

}

@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.category_card_lay, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}

@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {

holder.cat_name.setText(categoryData.get(position).getStrCategory());


}

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


public class MyViewHolder extends RecyclerView.ViewHolder {

TextView cat_name;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
cat_name=itemView.findViewById(R.id.cat_name);
}
}
}


Folder Tree:







10/  Then in MainActivity.






package com.example.mvpretrofit.views;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.widget.Toast;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.example.mvpretrofit.R;
import com.example.mvpretrofit.adpter.CategoryAdapter;
import com.example.mvpretrofit.models.CategoryData;
import com.example.mvpretrofit.presenter.MainPresenter;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements MainView {
CategoryAdapter customAdapter;
RecyclerView recyclerview;

@SuppressLint("MissingInflatedId")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);

MainPresenter mainPresenter=new MainPresenter(this);//
mainPresenter.getCategory();


recyclerview=findViewById(R.id.recycler);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerview.setLayoutManager(linearLayoutManager);

}

@Override
public void categoryList(ArrayList<CategoryData> categoryList) {

customAdapter =new CategoryAdapter(categoryList);
recyclerview.setAdapter(customAdapter);

Toast.makeText(this, categoryList.get(0).getIdCategory(), Toast.LENGTH_SHORT).show();
}
}






Run code then see output.


Comments