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 Product 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.

    Product CRUD Feature for Expense Manager Android App Using Retrofit

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

     


    1. Define the Product Model

    Define the ProductModel 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 ProductModel {

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


    public String getMessage() {
    return message;
    }

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

    public Boolean getStatus() {
    return status;
    }

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

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

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

    public ProductResultModel getResult() {
    return result;
    }

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

    package in.infovistar.expensemanager.models;

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

    public class ProductResultModel {
    @SerializedName("id")
    @Expose
    private String id;
    @SerializedName("name")
    @Expose
    private String name;
    @SerializedName("name_hi")
    @Expose
    private String nameHi;
    @SerializedName("sale_price")
    @Expose
    private String salePrice;
    @SerializedName("purchase_price")
    @Expose
    private String purchasePrice;
    @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 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 getSalePrice() {
    return salePrice;
    }

    public void setSalePrice(String salePrice) {
    this.salePrice = salePrice;
    }

    public String getPurchasePrice() {
    return purchasePrice;
    }

    public void setPurchasePrice(String purchasePrice) {
    this.purchasePrice = purchasePrice;
    }

    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 {

    // Product API
    // Product Create API
    @FormUrlEncoded
    @POST("product/create")
    Call<ProductModel> createProduct(@FieldMap HashMap<String, Object> hashMap);

    // Product List API
    @FormUrlEncoded
    @POST("product/list")
    Call<ProductModel> getProductList(@FieldMap HashMap<String, Object> hashMap);

    // Product Details API
    @FormUrlEncoded
    @POST("product/details")
    Call<ProductModel> getProductDetails(@FieldMap HashMap<String, Object> hashMap);

    // Product Update API
    @FormUrlEncoded
    @POST("product/update")
    Call<ProductModel> updateProduct(@FieldMap HashMap<String, Object> hashMap);

    // Customer Delete API
    @FormUrlEncoded
    @POST("product/delete")
    Call<ProductModel> deleteProduct(@FieldMap HashMap<String, Object> hashMap);

    }

     


    4. Create the Product 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.product.ProductActivity">

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

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

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

    <TextView
    android:id="@+id/tv_add_product"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/margin_12"
    android:text="@string/add_product"
    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 Product 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 products and includes buttons to create, update, and delete.

    Create the ProductActivity for Listing and Managing Products

    package in.infovistar.expensemanager.activities.product;

    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.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.customer.AddCustomerActivity;
    import in.infovistar.expensemanager.activities.login.LoginActivity;
    import in.infovistar.expensemanager.adapters.ProductAdapter;
    import in.infovistar.expensemanager.api.ApiService;
    import in.infovistar.expensemanager.models.ProductModel;
    import in.infovistar.expensemanager.models.ProductResultModel;
    import in.infovistar.expensemanager.session.Preferences;
    import retrofit2.Call;
    import retrofit2.Callback;
    import retrofit2.Response;

    public class ProductActivity extends AppCompatActivity {


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

    private Toolbar toolbar;
    private TextView toolbarTitle;

    private RecyclerView rvProduct;
    private TextView tvAddProduct;
    private List<ProductResultModel> resultModelList;
    private ProductAdapter productAdapter;
    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_product);

    init();

    rvProduct.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;
    loadProductList(startId);
    }
    }
    }
    });

    tvAddProduct.setOnClickListener(v -> {
    Intent intent = new Intent(context, AddProductActivity.class);
    startActivity(intent);
    });
    }

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

    startId = indexId = 0;
    resultModelList.clear();
    productAdapter.notifyDataSetChanged();
    loadProductList(startId);

    }

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

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

    @SuppressLint("NotifyDataSetChanged")
    private void populateProductList(List<ProductResultModel> results) {
    resultModelList.addAll(results);
    productAdapter.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.products));

    tvAddProduct = findViewById(R.id.tv_add_product);
    rvProduct = findViewById(R.id.rv_product);
    rvProduct.setLayoutManager(new LinearLayoutManager(context));
    resultModelList = new ArrayList<>();
    productAdapter = new ProductAdapter(resultModelList);
    rvProduct.setAdapter(productAdapter);
    }
    }

     


    6. Create the Product 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_product_name"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/product_name"
    android:textSize="@dimen/font_size_mini"
    style="@style/TextViewRegularFont"
    android:textColor="@color/black_333333"/>

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

    <TextView
    android:id="@+id/tv_sale_price"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:text="@string/sale_price"
    android:textSize="@dimen/font_size_small"
    android:textAlignment="textStart"
    style="@style/TextViewRegularFont"
    android:layout_marginTop="@dimen/margin_8"
    android:textColor="@color/black_333333"/>

    <TextView
    android:id="@+id/tv_purchase_price"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:textAlignment="textEnd"
    android:text="@string/purchase_price"
    android:textSize="@dimen/font_size_small"
    style="@style/TextViewRegularFont"
    android:layout_marginTop="@dimen/margin_8"
    android:textColor="@color/black_333333"/>

    </LinearLayout>

    <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 Products

    Create a ProductAdapter 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.UpdateCustomerActivity;
    import in.infovistar.expensemanager.activities.product.UpdateProductActivity;
    import in.infovistar.expensemanager.api.ApiService;
    import in.infovistar.expensemanager.models.CustomerModel;
    import in.infovistar.expensemanager.models.CustomerResultModel;
    import in.infovistar.expensemanager.models.ProductModel;
    import in.infovistar.expensemanager.models.ProductResultModel;
    import retrofit2.Call;
    import retrofit2.Callback;
    import retrofit2.Response;

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


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

    public ProductAdapter(List<ProductResultModel> resultModelList) {
    this.resultModelList = resultModelList;
    }

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

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    ProductResultModel resultModel = resultModelList.get(position);
    holder.setName(resultModel.getName());
    holder.setPurchasePrice(resultModel.getPurchasePrice());
    holder.setSalePrice(resultModel.getSalePrice());
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {

    private TextView tvProductName;
    private TextView tvSalePrice;
    private TextView tvPurchasePrice;

    private TextView tvEdit;
    private TextView tvDelete;

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

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

    tvProductName = itemView.findViewById(R.id.tv_product_name);
    tvSalePrice = itemView.findViewById(R.id.tv_sale_price);
    tvPurchasePrice = itemView.findViewById(R.id.tv_purchase_price);

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

    tvEdit.setOnClickListener(v -> {
    ProductResultModel resultModel = resultModelList.get(getBindingAdapterPosition());
    Intent intent = new Intent(context, UpdateProductActivity.class);
    intent.putExtra("product_id", resultModel.getId());
    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();
    deleteProduct(position);
    }).setNegativeButton(R.string.no, (dialog, id) -> {
    dialog.cancel();
    });
    AlertDialog alert = builder.create();
    alert.show();
    }

    private void deleteProduct(int position) {
    ProductResultModel resultModel = resultModelList.get(position);
    HashMap<String, Object> hashMap = new HashMap<>();
    hashMap.put("product_id", resultModel.getId());
    apiService
    .deleteProduct(hashMap)
    .enqueue(new Callback<ProductModel>() {
    @Override
    public void onResponse(Call<ProductModel> call, Response<ProductModel> 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<ProductModel> call, Throwable t) {
    Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show();
    }
    });
    }

    public void setName(String name) {
    tvProductName.setText(name);
    }

    public void setPurchasePrice(String purchasePrice) {
    tvPurchasePrice.setText(purchasePrice);
    }

    public void setSalePrice(String salePrice) {
    tvSalePrice.setText(salePrice);
    }
    }
    }

     


    8. Create Add Product Activity

    Create the AddProductActivity to create a new product

    package in.infovistar.expensemanager.activities.product;

    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.ProductModel;
    import in.infovistar.expensemanager.session.Preferences;
    import retrofit2.Call;
    import retrofit2.Callback;
    import retrofit2.Response;

    public class AddProductActivity 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 tilPurchasePrice;
    private TextInputLayout tilSalePrice;
    private TextView tvAddProduct;

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

    init();

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

    }

    private void validate() {
    if(tilName.getEditText().getText().toString().trim().isEmpty()) {
    tilName.setError(getText(R.string.please_enter_product_name));
    } else {
    tilName.setErrorEnabled(false);
    if(tilPurchasePrice.getEditText().getText().toString().trim().isEmpty()) {
    tilPurchasePrice.setError(getText(R.string.please_enter_purchase_price));
    } else {
    tilPurchasePrice.setErrorEnabled(false);
    if(tilSalePrice.getEditText().getText().toString().trim().isEmpty()) {
    tilSalePrice.setError(getText(R.string.please_enter_sale_price));
    } else {
    tilSalePrice.setErrorEnabled(false);
    submit();
    }
    }
    }
    }

    private void submit() {
    HashMap<String, Object> hashMap = new HashMap<>();
    hashMap.put("name", tilName.getEditText().getText().toString());
    hashMap.put("purchase_price", tilPurchasePrice.getEditText().getText().toString());
    hashMap.put("sale_price", tilSalePrice.getEditText().getText().toString());
    hashMap.put("status", "1");

    apiService
    .createProduct(hashMap)
    .enqueue(new Callback<ProductModel>() {
    @Override
    public void onResponse(Call<ProductModel> call, Response<ProductModel> 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<ProductModel> 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_product));

    tilName = findViewById(R.id.til_name);
    tilPurchasePrice = findViewById(R.id.til_purchase_price);
    tilSalePrice = findViewById(R.id.til_sale_price);
    tvAddProduct = findViewById(R.id.tv_add_product);
    }
    }

     


    9. Create Add Product 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.product.AddProductActivity">

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

    <com.google.android.material.textfield.TextInputLayout
    android:id="@+id/til_purchase_price"
    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/purchase_price"
    android:textSize="@dimen/font_size_medium"
    android:background="@drawable/edittext_bg"
    style="@style/EditTextRegularFont"
    android:inputType="numberDecimal"
    android:maxLines="1"/>

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

    <com.google.android.material.textfield.TextInputLayout
    android:id="@+id/til_sale_price"
    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/sale_price"
    android:textSize="@dimen/font_size_medium"
    android:background="@drawable/edittext_bg"
    style="@style/EditTextRegularFont"
    android:inputType="numberDecimal"
    android:maxLines="1"/>

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

    <TextView
    android:id="@+id/tv_add_product"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/margin_12"
    android:text="@string/add_product"
    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>

     


    10. Create Update Product Activity

    Create the UpdateProductActivity to update the existing product

    package in.infovistar.expensemanager.activities.product;

    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.models.ProductModel;
    import in.infovistar.expensemanager.models.ProductResultModel;
    import in.infovistar.expensemanager.session.Preferences;
    import retrofit2.Call;
    import retrofit2.Callback;
    import retrofit2.Response;

    public class UpdateProductActivity 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 tilPurchasePrice;
    private TextInputLayout tilSalePrice;
    private TextView tvAddProduct;
    private String productId;

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

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

    init();

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

    loadProduct();

    }

    private void loadProduct() {
    HashMap<String, Object> hashMap = new HashMap<>();
    hashMap.put("product_id", productId);
    apiService
    .getProductDetails(hashMap)
    .enqueue(new Callback<ProductModel>() {
    @Override
    public void onResponse(Call<ProductModel> call, Response<ProductModel> response) {
    if(response.body() != null) {
    if(response.body().getStatus()) {
    populateProduct(response.body().getResult());
    }
    }
    }

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

    }
    });
    }

    private void populateProduct(ProductResultModel result) {
    tilName.getEditText().setText(result.getName());
    tilSalePrice.getEditText().setText(result.getSalePrice());
    tilPurchasePrice.getEditText().setText(result.getPurchasePrice());
    }

    private void validate() {
    if(tilName.getEditText().getText().toString().trim().isEmpty()) {
    tilName.setError(getText(R.string.please_enter_product_name));
    } else {
    tilName.setErrorEnabled(false);
    if(tilPurchasePrice.getEditText().getText().toString().trim().isEmpty()) {
    tilPurchasePrice.setError(getText(R.string.please_enter_purchase_price));
    } else {
    tilPurchasePrice.setErrorEnabled(false);
    if(tilSalePrice.getEditText().getText().toString().trim().isEmpty()) {
    tilSalePrice.setError(getText(R.string.please_enter_sale_price));
    } else {
    tilSalePrice.setErrorEnabled(false);
    submit();
    }
    }
    }
    }

    private void submit() {
    HashMap<String, Object> hashMap = new HashMap<>();
    hashMap.put("product_id", productId);
    hashMap.put("name", tilName.getEditText().getText().toString());
    hashMap.put("purchase_price", tilPurchasePrice.getEditText().getText().toString());
    hashMap.put("sale_price", tilSalePrice.getEditText().getText().toString());
    hashMap.put("status", "1");

    apiService
    .updateProduct(hashMap)
    .enqueue(new Callback<ProductModel>() {
    @Override
    public void onResponse(Call<ProductModel> call, Response<ProductModel> 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<ProductModel> 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_product));

    tilName = findViewById(R.id.til_name);
    tilPurchasePrice = findViewById(R.id.til_purchase_price);
    tilSalePrice = findViewById(R.id.til_sale_price);
    tvAddProduct = findViewById(R.id.tv_add_product);
    tvAddProduct.setText(getString(R.string.update_product));
    }
    }