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