Course Content
Expense Manager App – Login
0/1
Expense Manager App – Product
0/1
Expense Manager Android App
    About Lesson

    Here’s a guide on implementing Customer CRUD (Create, Read, Update, Delete) operations in the Expense Manager Android App using Retrofit. This implementation includes setting up Retrofit to interact with backend APIs to manage customer data, create the necessary UI components, and integrate them with the app.

    Customer CRUD Feature for Expense Manager Android App Using Retrofit

    Customer CRUD functionality allows you to manage customer data within the Expense Manager app. This involves creating, reading, updating, and deleting customer information, all handled through Retrofit for seamless API communication.

     


    1. Define the Customer Model

    Define the CustomerModel model class to represent the customer data structure that will be used in API requests and responses.

    package in.infovistar.expensemanager.models;

    import com.google.gson.annotations.Expose;
    import com.google.gson.annotations.SerializedName;

    import java.util.List;

    public class CustomerModel {

    @SerializedName("status")
    @Expose
    private Boolean status;
    @SerializedName("message")
    @Expose
    private String message;
    @SerializedName("results")
    @Expose
    private List<CustomerResultModel> results;
    @SerializedName("result")
    @Expose
    private CustomerResultModel result;

    public Boolean getStatus() {
    return status;
    }

    public void setStatus(Boolean status) {
    this.status = status;
    }

    public String getMessage() {
    return message;
    }

    public void setMessage(String message) {
    this.message = message;
    }

    public List<CustomerResultModel> getResults() {
    return results;
    }

    public void setResults(List<CustomerResultModel> results) {
    this.results = results;
    }

    public CustomerResultModel getResult() {
    return result;
    }

    public void setResult(CustomerResultModel result) {
    this.result = result;
    }
    }

    package in.infovistar.expensemanager.models;

    import com.google.gson.annotations.Expose;
    import com.google.gson.annotations.SerializedName;

    public class CustomerResultModel {

    @SerializedName("id")
    @Expose
    private String id;
    @SerializedName("type")
    @Expose
    private String type;
    @SerializedName("name")
    @Expose
    private String name;
    @SerializedName("name_hi")
    @Expose
    private String nameHi;
    @SerializedName("mobile_country")
    @Expose
    private String mobileCountry;
    @SerializedName("mobile_number")
    @Expose
    private String mobileNumber;
    @SerializedName("email")
    @Expose
    private String email;
    @SerializedName("password")
    @Expose
    private String password;
    @SerializedName("address")
    @Expose
    private String address;
    @SerializedName("image_url")
    @Expose
    private String imageUrl;
    @SerializedName("account_holder_name")
    @Expose
    private String accountHolderName;
    @SerializedName("account_number")
    @Expose
    private String accountNumber;
    @SerializedName("ifsc_code")
    @Expose
    private String ifscCode;
    @SerializedName("bank_name")
    @Expose
    private String bankName;
    @SerializedName("city_id")
    @Expose
    private Object cityId;
    @SerializedName("city_name")
    @Expose
    private Object cityName;
    @SerializedName("company_name")
    @Expose
    private Object companyName;
    @SerializedName("ip_address")
    @Expose
    private String ipAddress;
    @SerializedName("created_at")
    @Expose
    private String createdAt;
    @SerializedName("updated_at")
    @Expose
    private String updatedAt;
    @SerializedName("status")
    @Expose
    private String status;

    public String getId() {
    return id;
    }

    public void setId(String id) {
    this.id = id;
    }

    public String getType() {
    return type;
    }

    public void setType(String type) {
    this.type = type;
    }

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public String getNameHi() {
    return nameHi;
    }

    public void setNameHi(String nameHi) {
    this.nameHi = nameHi;
    }

    public String getMobileCountry() {
    return mobileCountry;
    }

    public void setMobileCountry(String mobileCountry) {
    this.mobileCountry = mobileCountry;
    }

    public String getMobileNumber() {
    return mobileNumber;
    }

    public void setMobileNumber(String mobileNumber) {
    this.mobileNumber = mobileNumber;
    }

    public String getEmail() {
    return email;
    }

    public void setEmail(String email) {
    this.email = email;
    }

    public String getPassword() {
    return password;
    }

    public void setPassword(String password) {
    this.password = password;
    }

    public String getAddress() {
    return address;
    }

    public void setAddress(String address) {
    this.address = address;
    }

    public String getImageUrl() {
    return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
    this.imageUrl = imageUrl;
    }

    public String getAccountHolderName() {
    return accountHolderName;
    }

    public void setAccountHolderName(String accountHolderName) {
    this.accountHolderName = accountHolderName;
    }

    public String getAccountNumber() {
    return accountNumber;
    }

    public void setAccountNumber(String accountNumber) {
    this.accountNumber = accountNumber;
    }

    public String getIfscCode() {
    return ifscCode;
    }

    public void setIfscCode(String ifscCode) {
    this.ifscCode = ifscCode;
    }

    public String getBankName() {
    return bankName;
    }

    public void setBankName(String bankName) {
    this.bankName = bankName;
    }

    public Object getCityId() {
    return cityId;
    }

    public void setCityId(Object cityId) {
    this.cityId = cityId;
    }

    public Object getCityName() {
    return cityName;
    }

    public void setCityName(Object cityName) {
    this.cityName = cityName;
    }

    public Object getCompanyName() {
    return companyName;
    }

    public void setCompanyName(Object companyName) {
    this.companyName = companyName;
    }

    public String getIpAddress() {
    return ipAddress;
    }

    public void setIpAddress(String ipAddress) {
    this.ipAddress = ipAddress;
    }

    public String getCreatedAt() {
    return createdAt;
    }

    public void setCreatedAt(String createdAt) {
    this.createdAt = createdAt;
    }

    public String getUpdatedAt() {
    return updatedAt;
    }

    public void setUpdatedAt(String updatedAt) {
    this.updatedAt = updatedAt;
    }

    public String getStatus() {
    return status;
    }

    public void setStatus(String status) {
    this.status = status;
    }
    }

    2. Create the Toolbar Layout

    toolbar.xml
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.appcompat.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar"
    android:background="@color/actionbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <RelativeLayout
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
    android:gravity="center_vertical"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
    android:textSize="@dimen/font_size_medium"
    android:textColor="@color/white"
    android:ellipsize="end"
    android:gravity="start|center_vertical|center_horizontal|center"
    android:id="@+id/toolbar_title"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:maxLines="1"
    android:text="@string/app_name"
    style="@style/TextViewRegularFont"/>

    </LinearLayout>

    </RelativeLayout>

    </androidx.appcompat.widget.Toolbar>

    3. Define the ApiService Interface

    Define the API endpoints for Customer CRUD operations in your ApiService interface.

    package in.infovistar.expensemanager.api;

    import java.util.HashMap;

    import in.infovistar.expensemanager.models.CustomerModel;
    import in.infovistar.expensemanager.models.LoginModel;
    import retrofit2.Call;
    import retrofit2.http.FieldMap;
    import retrofit2.http.FormUrlEncoded;
    import retrofit2.http.POST;

    public interface ApiService {

    // Customer APIs
    // Customer List API
    @FormUrlEncoded
    @POST("customer/list")
    Call<CustomerModel> getCustomerList(@FieldMap HashMap<String, Object> hashMap);

    }

     


    4. Create the Customer List Screen Layout

    <?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:orientation="vertical"
    tools:context=".activities.customer.CustomerActivity">

    <include
    layout="@layout/toolbar"/>

    <RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
    android:id="@+id/rv_customer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_above="@id/tv_add_customer"
    android:padding="@dimen/padding_12"/>

    <TextView
    android:id="@+id/tv_add_customer"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/margin_12"
    android:text="@string/add_customer"
    android:textAllCaps="false"
    android:textSize="@dimen/font_size_medium"
    android:textColor="@color/white"
    android:textAlignment="center"
    android:background="@drawable/login_button_bg"
    style="@style/TextViewMediumFont"
    android:layout_alignParentBottom="true"/>

    </RelativeLayout>

    </LinearLayout>

     


    5. Create Customer List Activity

    Here’s how you can implement the main CRUD operations using separate activities or fragments for the UI. The examples below will focus on the main activity that lists customers and includes buttons to create, update, and delete.

    Create the CustomerActivity for Listing and Managing Customers

    package in.infovistar.expensemanager.activities.customer;

    import androidx.annotation.NonNull;
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.appcompat.widget.Toolbar;
    import androidx.recyclerview.widget.LinearLayoutManager;
    import androidx.recyclerview.widget.RecyclerView;

    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.TextView;
    import android.widget.Toast;

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

    import in.infovistar.expensemanager.ExpenseManagerApp;
    import in.infovistar.expensemanager.R;
    import in.infovistar.expensemanager.activities.login.LoginActivity;
    import in.infovistar.expensemanager.adapters.CustomerAdapter;
    import in.infovistar.expensemanager.api.ApiService;
    import in.infovistar.expensemanager.models.CustomerModel;
    import in.infovistar.expensemanager.models.CustomerResultModel;
    import in.infovistar.expensemanager.session.Preferences;
    import retrofit2.Call;
    import retrofit2.Callback;
    import retrofit2.Response;

    public class CustomerActivity extends AppCompatActivity {


    private ExpenseManagerApp expenseManagerApp;
    private Context context;
    private Preferences preferences;
    private ApiService apiService;

    private Toolbar toolbar;
    private TextView toolbarTitle;

    private RecyclerView rvCustomer;
    private TextView tvAddCustomer;
    private CustomerAdapter customerAdapter;
    private List<CustomerResultModel> resultModelList;
    private String type = "customer";
    private int startId = 0;
    private int indexId = 0;
    private int loadLimit = 20;

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

    init();

    rvCustomer.addOnScrollListener(new RecyclerView.OnScrollListener() {

    @Override
    public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
    super.onScrolled(recyclerView, dx, dy);
    if (dy > 0) {
    if (!recyclerView.canScrollVertically(RecyclerView.FOCUS_DOWN)) {
    indexId++;
    startId = loadLimit * indexId;
    loadCustomerList(startId);
    }
    }
    }
    });
    tvAddCustomer.setOnClickListener(v -> {
    Intent intent = new Intent(context, AddCustomerActivity.class);
    intent.putExtra("type", type);
    startActivity(intent);
    });
    }

    @SuppressLint("NotifyDataSetChanged")
    @Override
    protected void onResume() {
    super.onResume();

    startId = indexId = 0;
    resultModelList.clear();
    customerAdapter.notifyDataSetChanged();
    loadCustomerList(startId);

    }

    private void loadCustomerList(int startId) {
    HashMap<String, Object> hashMap = new HashMap<>();
    hashMap.put("type", type);
    hashMap.put("start_limit", startId);
    hashMap.put("load_limit", loadLimit);
    apiService
    .getCustomerList(hashMap)
    .enqueue(new Callback<CustomerModel>() {
    @Override
    public void onResponse(Call<CustomerModel> call, Response<CustomerModel> response) {
    if(response.body() != null) {
    if(response.body().getStatus()) {
    populateCustomerList(response.body().getResults());
    }
    }
    }

    @Override
    public void onFailure(Call<CustomerModel> call, Throwable t) {
    Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show();
    }
    });
    }

    @SuppressLint("NotifyDataSetChanged")
    private void populateCustomerList(List<CustomerResultModel> results) {
    resultModelList.addAll(results);
    customerAdapter.notifyDataSetChanged();
    }

    private void init() {
    context = this;
    expenseManagerApp = (ExpenseManagerApp) getApplicationContext();
    preferences = expenseManagerApp.getPreferences();
    apiService = expenseManagerApp.getApiService();

    if(preferences.getLogin() == null) {
    startActivity(new Intent(context, LoginActivity.class));
    finish();
    }

    toolbar = findViewById(R.id.toolbar);
    toolbarTitle = findViewById(R.id.toolbar_title);
    setSupportActionBar(toolbar);
    toolbarTitle.setText(getString(R.string.customers));

    tvAddCustomer = findViewById(R.id.tv_add_customer);
    rvCustomer = findViewById(R.id.rv_customer);
    rvCustomer.setLayoutManager(new LinearLayoutManager(context));
    resultModelList = new ArrayList<>();
    customerAdapter = new CustomerAdapter(resultModelList);
    rvCustomer.setAdapter(customerAdapter);
    }
    }

     


    6. Create the Customer Adapter Screen Layout

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="@dimen/padding_12"
    android:background="@drawable/login_card_bg">

    <TextView
    android:id="@+id/tv_customer_name"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/customer_name"
    android:textSize="@dimen/font_size_mini"
    style="@style/TextViewRegularFont"
    android:textColor="@color/black_333333"/>

    <TextView
    android:id="@+id/tv_mobile_number"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/mobile_no"
    android:textSize="@dimen/font_size_small"
    style="@style/TextViewRegularFont"
    android:layout_marginTop="@dimen/margin_8"
    android:textColor="@color/black_333333"/>

    <View
    android:layout_width="match_parent"
    android:layout_height="@dimen/margin_0_5"
    android:background="@color/dbdbdb"
    android:layout_marginTop="@dimen/margin_8" />

    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:weightSum="2">

    <TextView
    android:id="@+id/tv_edit"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:text="@string/edit"
    style="@style/TextViewRegularFont"
    android:textAlignment="center"
    android:padding="@dimen/padding_8"
    android:textColor="@color/black_333333"
    android:textSize="@dimen/font_size_mini"/>

    <View
    android:layout_width="@dimen/margin_0_5"
    android:layout_height="match_parent"
    android:background="@color/dbdbdb"
    android:layout_marginTop="@dimen/margin_8" />

    <TextView
    android:id="@+id/tv_delete"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:text="@string/delete"
    style="@style/TextViewRegularFont"
    android:textAlignment="center"
    android:padding="@dimen/padding_8"
    android:textColor="@color/black_333333"
    android:textSize="@dimen/font_size_mini"/>

    </LinearLayout>

    </LinearLayout>

     


    7. RecyclerView Adapter for Displaying Customers

    Create a CustomerAdapter to manage the display of customer data in a RecyclerView.

    package in.infovistar.expensemanager.adapters;

    import android.content.Context;
    import android.content.Intent;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    import android.widget.Toast;

    import androidx.annotation.NonNull;
    import androidx.appcompat.app.AlertDialog;
    import androidx.recyclerview.widget.RecyclerView;

    import java.util.HashMap;
    import java.util.List;

    import in.infovistar.expensemanager.ExpenseManagerApp;
    import in.infovistar.expensemanager.R;
    import in.infovistar.expensemanager.activities.customer.AddCustomerActivity;
    import in.infovistar.expensemanager.activities.customer.UpdateCustomerActivity;
    import in.infovistar.expensemanager.api.ApiService;
    import in.infovistar.expensemanager.models.CustomerModel;
    import in.infovistar.expensemanager.models.CustomerResultModel;
    import in.infovistar.expensemanager.session.Preferences;
    import retrofit2.Call;
    import retrofit2.Callback;
    import retrofit2.Response;

    public class CustomerAdapter extends RecyclerView.Adapter<CustomerAdapter.ViewHolder> {


    private ExpenseManagerApp expenseManagerApp;
    private ApiService apiService;
    private Context context;
    private List<CustomerResultModel> resultModelList;

    public CustomerAdapter(List<CustomerResultModel> resultModelList) {
    this.resultModelList = resultModelList;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_customer, parent, false);
    return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    CustomerResultModel resultModel = resultModelList.get(position);
    holder.setCustomerName(resultModel.getName());
    holder.setMobileNumber(resultModel.getMobileCountry() + resultModel.getMobileNumber());
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {

    private TextView tvCustomerName;
    private TextView tvMobileNumber;

    private TextView tvEdit;
    private TextView tvDelete;

    public ViewHolder(@NonNull View itemView) {
    super(itemView);

    context = itemView.getContext();
    expenseManagerApp = (ExpenseManagerApp) context.getApplicationContext();
    apiService = expenseManagerApp.getApiService();

    tvCustomerName = itemView.findViewById(R.id.tv_customer_name);
    tvMobileNumber = itemView.findViewById(R.id.tv_mobile_number);

    tvEdit = itemView.findViewById(R.id.tv_edit);
    tvDelete = itemView.findViewById(R.id.tv_delete);
    }

    public void setCustomerName(String name) {
    tvCustomerName.setText(name);
    }

    public void setMobileNumber(String mobileNumber) {
    tvMobileNumber.setText(mobileNumber);
    }
    }
    }

     


    8. Testing and Integration

    Customer List | Expense Manager Android App