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 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);

    // Customer Create API
    @FormUrlEncoded
    @POST("customer/create")
    Call<CustomerModel> createCustomer(@FieldMap HashMap<String, Object> hashMap);

    // Customer Details API
    @FormUrlEncoded
    @POST("customer/details")
    Call<CustomerModel> getCustomerDetails(@FieldMap HashMap<String, Object> hashMap);

    // Customer Update API
    @FormUrlEncoded
    @POST("customer/update")
    Call<CustomerModel> updateCustomer(@FieldMap HashMap<String, Object> hashMap);

    // Customer Delete API
    @FormUrlEncoded
    @POST("customer/update")
    Call<CustomerModel> deleteCustomer(@FieldMap HashMap<String, Object> hashMap);


    }

     


    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. Create the Add Customer Screen Layout

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

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

    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="@dimen/padding_12">

    <com.google.android.material.textfield.TextInputLayout
    android:id="@+id/til_name"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:boxStrokeWidth="0dp"
    app:boxStrokeWidthFocused="0dp"
    android:layout_marginTop="@dimen/margin_16">

    <EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="@string/customer_name"
    android:textSize="@dimen/font_size_medium"
    android:background="@drawable/edittext_bg"
    style="@style/EditTextRegularFont"
    android:inputType="textPersonName"
    android:maxLines="1"/>

    <requestFocus/>

    </com.google.android.material.textfield.TextInputLayout>

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

    <com.google.android.material.textfield.TextInputLayout
    android:id="@+id/til_mobile_country"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    app:boxStrokeWidth="0dp"
    app:boxStrokeWidthFocused="0dp"
    android:layout_marginTop="@dimen/margin_16"
    android:layout_marginEnd="@dimen/margin_4">

    <EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="@string/country_code"
    android:textSize="@dimen/font_size_medium"
    android:background="@drawable/edittext_bg"
    style="@style/EditTextRegularFont"
    android:inputType="phone"
    android:text="@string/_91"
    android:focusable="false"
    android:maxLength="10"
    android:maxLines="1"/>

    <requestFocus/>

    </com.google.android.material.textfield.TextInputLayout>

    <com.google.android.material.textfield.TextInputLayout
    android:id="@+id/til_mobile_number"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="2"
    app:boxStrokeWidth="0dp"
    app:boxStrokeWidthFocused="0dp"
    android:layout_marginTop="@dimen/margin_16"
    android:layout_marginStart="@dimen/margin_4">

    <EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="@string/mobile_no"
    android:textSize="@dimen/font_size_medium"
    android:background="@drawable/edittext_bg"
    style="@style/EditTextRegularFont"
    android:inputType="phone"
    android:maxLength="10"
    android:maxLines="1"/>

    <requestFocus/>

    </com.google.android.material.textfield.TextInputLayout>

    </LinearLayout>

    <com.google.android.material.textfield.TextInputLayout
    android:id="@+id/til_address"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:boxStrokeWidth="0dp"
    app:boxStrokeWidthFocused="0dp"
    android:layout_marginTop="@dimen/margin_16">

    <EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="@string/address"
    android:textSize="@dimen/font_size_medium"
    android:background="@drawable/edittext_bg"
    style="@style/EditTextRegularFont"
    android:inputType="text"
    android:maxLines="4"/>

    <requestFocus/>

    </com.google.android.material.textfield.TextInputLayout>

    <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"/>

    </LinearLayout>

    </LinearLayout>

     


    4 . Create Add Customer 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.

    package in.infovistar.expensemanager.activities.customer;

    import androidx.appcompat.app.AppCompatActivity;
    import androidx.appcompat.widget.Toolbar;

    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 com.google.android.material.textfield.TextInputLayout;

    import java.util.HashMap;

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

    public class AddCustomerActivity extends AppCompatActivity {


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

    private Toolbar toolbar;
    private TextView toolbarTitle;

    private TextInputLayout tilName;
    private TextInputLayout tilMobileCountry;
    private TextInputLayout tilMobileNumber;
    private TextInputLayout tilAddress;
    private TextView tvAddCustomer;

    private String type;

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

    if(getIntent() != null) {
    type = getIntent().getStringExtra("type");
    }

    init();

    tvAddCustomer.setOnClickListener(v -> {
    validate();
    });

    }

    private void validate() {
    if(tilName.getEditText().getText().toString().trim().isEmpty()) {
    tilName.setError(getText(R.string.please_enter_customer_name));
    } else {
    tilName.setErrorEnabled(false);
    if(tilMobileNumber.getEditText().getText().toString().trim().isEmpty()
    || tilMobileNumber.getEditText().getText().toString().trim().length() < 10) {
    tilMobileNumber.setError(getText(R.string.please_enter_10_digit_mobile_number));
    } else {
    tilMobileCountry.setErrorEnabled(false);
    submit();
    }
    }
    }

    private void submit() {
    HashMap<String, Object> hashMap = new HashMap<>();
    hashMap.put("type", type);
    hashMap.put("name", tilName.getEditText().getText().toString());
    hashMap.put("mobile_country", tilMobileCountry.getEditText().getText().toString());
    hashMap.put("mobile_number", tilMobileNumber.getEditText().getText().toString());
    hashMap.put("address", tilAddress.getEditText().getText().toString());
    hashMap.put("status", "1");

    apiService
    .createCustomer(hashMap)
    .enqueue(new Callback<CustomerModel>() {
    @Override
    public void onResponse(Call<CustomerModel> call, Response<CustomerModel> response) {
    if(response.body() != null) {
    Toast.makeText(context, response.body().getMessage(), Toast.LENGTH_SHORT).show();
    if(response.body().getStatus()) {
    finish();
    }
    }
    }

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

    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.add_customer));

    tilName = findViewById(R.id.til_name);
    tilMobileCountry = findViewById(R.id.til_mobile_country);
    tilMobileNumber = findViewById(R.id.til_mobile_number);
    tilAddress = findViewById(R.id.til_address);
    tvAddCustomer = findViewById(R.id.tv_add_customer);
    }
    }

     


    4 . Create Update Customer Activity

    package in.infovistar.expensemanager.activities.customer;

    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    import android.widget.TextView;
    import android.widget.Toast;

    import androidx.appcompat.app.AppCompatActivity;
    import androidx.appcompat.widget.Toolbar;

    import com.google.android.material.textfield.TextInputLayout;

    import java.util.HashMap;

    import in.infovistar.expensemanager.ExpenseManagerApp;
    import in.infovistar.expensemanager.R;
    import in.infovistar.expensemanager.activities.login.LoginActivity;
    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 UpdateCustomerActivity extends AppCompatActivity {

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

    private Toolbar toolbar;
    private TextView toolbarTitle;

    private TextInputLayout tilName;
    private TextInputLayout tilMobileCountry;
    private TextInputLayout tilMobileNumber;
    private TextInputLayout tilAddress;
    private TextView tvAddCustomer;


    private String type;
    private String customerId;

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

    if(getIntent() != null) {
    type = getIntent().getStringExtra("type");
    customerId = getIntent().getStringExtra("customer_id");
    }

    init();

    loadCustomer();

    tvAddCustomer.setOnClickListener(v -> {
    validate();
    });

    }

    private void loadCustomer() {
    HashMap<String, Object> hashMap = new HashMap<>();
    hashMap.put("customer_id", customerId);
    apiService
    .getCustomerDetails(hashMap)
    .enqueue(new Callback<CustomerModel>() {
    @Override
    public void onResponse(Call<CustomerModel> call, Response<CustomerModel> response) {
    if(response.body() != null) {
    if(response.body().getStatus()) {
    populateCustomer(response.body().getResult());
    }
    }
    }

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

    }
    });
    }

    private void populateCustomer(CustomerResultModel result) {
    tilName.getEditText().setText(result.getName());
    tilMobileCountry.getEditText().setText(result.getMobileCountry());
    tilMobileNumber.getEditText().setText(result.getMobileNumber());
    tilAddress.getEditText().setText(result.getAddress());
    }

    private void validate() {
    if(tilName.getEditText().getText().toString().trim().isEmpty()) {
    tilName.setError(getText(R.string.please_enter_customer_name));
    } else {
    tilName.setErrorEnabled(false);
    if(tilMobileNumber.getEditText().getText().toString().trim().isEmpty()
    || tilMobileNumber.getEditText().getText().toString().trim().length() < 10) {
    tilMobileNumber.setError(getText(R.string.please_enter_10_digit_mobile_number));
    } else {
    tilMobileCountry.setErrorEnabled(false);
    submit();
    }
    }
    }

    private void submit() {
    HashMap<String, Object> hashMap = new HashMap<>();
    hashMap.put("type", type);
    hashMap.put("customer_id", customerId);
    hashMap.put("name", tilName.getEditText().getText().toString());
    hashMap.put("mobile_country", tilMobileCountry.getEditText().getText().toString());
    hashMap.put("mobile_number", tilMobileNumber.getEditText().getText().toString());
    hashMap.put("address", tilAddress.getEditText().getText().toString());
    hashMap.put("status", "1");

    apiService
    .updateCustomer(hashMap)
    .enqueue(new Callback<CustomerModel>() {
    @Override
    public void onResponse(Call<CustomerModel> call, Response<CustomerModel> response) {
    if(response.body() != null) {
    Toast.makeText(context, response.body().getMessage(), Toast.LENGTH_SHORT).show();
    if(response.body().getStatus()) {
    finish();
    }
    }
    }

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

    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.update_customer));

    tilName = findViewById(R.id.til_name);
    tilMobileCountry = findViewById(R.id.til_mobile_country);
    tilMobileNumber = findViewById(R.id.til_mobile_number);
    tilAddress = findViewById(R.id.til_address);
    tvAddCustomer = findViewById(R.id.tv_add_customer);
    tvAddCustomer.setText(getString(R.string.update_customer));
    }
    }

     


    5. RecyclerView Adapter for Displaying Customers

    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);

    tvEdit.setOnClickListener(v -> {
    CustomerResultModel resultModel = resultModelList.get(getBindingAdapterPosition());
    Intent intent = new Intent(context, UpdateCustomerActivity.class);
    intent.putExtra("customer_id", resultModel.getId());
    intent.putExtra("type", resultModel.getType());
    context.startActivity(intent);
    });

    tvDelete.setOnClickListener(v -> {
    showDeleteAlertDialog(getBindingAdapterPosition());
    });
    }

    private void showDeleteAlertDialog(int position) {
    AlertDialog.Builder builder = new AlertDialog.Builder(context);
    builder.setMessage(R.string.delete_message)
    .setCancelable(false)
    .setPositiveButton(R.string.yes, (dialog, id) -> {
    dialog.dismiss();
    deleteCustomer(position);
    }).setNegativeButton(R.string.no, (dialog, id) -> {
    dialog.cancel();
    });
    AlertDialog alert = builder.create();
    alert.show();
    }

    private void deleteCustomer(int position) {
    CustomerResultModel resultModel = resultModelList.get(position);
    HashMap<String, Object> hashMap = new HashMap<>();
    hashMap.put("customer_id", resultModel.getId());
    apiService
    .deleteCustomer(hashMap)
    .enqueue(new Callback<CustomerModel>() {
    @Override
    public void onResponse(Call<CustomerModel> call, Response<CustomerModel> response) {
    if(response.body() != null) {
    Toast.makeText(context, response.body().getMessage(), Toast.LENGTH_SHORT).show();
    if(response.body().getStatus()) {
    resultModelList.remove(position);
    notifyItemRemoved(position);
    }
    }
    }

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

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

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

     


    6. Testing and Integration

    Create, Update and Delete Customer | Expense Manager Android App
    Add Customer

     

    Create, Update and Delete Customer | Expense Manager Android App
    Update Customer