replaced observer in viewmodels to observe only once to fix memleek

This commit is contained in:
Alex
2026-04-11 15:46:30 -06:00
parent bb62b5d352
commit cd74e5f06f
21 changed files with 321 additions and 45 deletions

View File

@@ -113,6 +113,7 @@ public class AdoptionDetailFragment extends Fragment {
binding.spinnerAdoptionCustomer.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (isUpdatingUI) return;
viewModel.onCustomerSelected(position);
}
@Override
@@ -122,6 +123,7 @@ public class AdoptionDetailFragment extends Fragment {
binding.spinnerAdoptionStore.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (isUpdatingUI) return;
viewModel.onStoreSelected(position);
}
@Override

View File

@@ -89,6 +89,7 @@ public class AppointmentDetailFragment extends Fragment {
binding.spinnerCustomer.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (isUpdatingUI) return;
viewModel.onCustomerSelected(position);
}
@Override
@@ -98,6 +99,7 @@ public class AppointmentDetailFragment extends Fragment {
binding.spinnerStore.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (isUpdatingUI) return;
viewModel.onStoreSelected(position);
}
@Override

View File

@@ -13,6 +13,8 @@ import com.example.petstoremobile.repositories.StoreRepository;
import com.example.petstoremobile.utils.DateTimeUtils;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -71,18 +73,17 @@ public class AdoptionDetailViewModel extends ViewModel {
state.saveButtonText = isEditing ? "Save" : "Add";
state.isAdoptionIdVisible = isEditing;
state.isDeleteVisible = isEditing;
state.isFeeEnabled = false; // fee is always read-only
state.isFeeEnabled = false;
if (!isEditing) {
state.isCustomerEnabled = true;
state.isStoreEnabled = true;
state.isPetEnabled = false; // until customer selected
state.isEmployeeEnabled = false; // until store selected
state.isPetEnabled = false;
state.isEmployeeEnabled = false;
state.isDateEnabled = true;
state.isStatusEnabled = true;
state.availableStatuses = new String[]{"Pending"};
state.selectedStatus = "Pending";
} else {
// edit: date-based logic applied after load
state.isCustomerEnabled = false;
state.isStoreEnabled = false;
state.isPetEnabled = false;
@@ -95,12 +96,12 @@ public class AdoptionDetailViewModel extends ViewModel {
public void loadInitialFormData(boolean isEditing) {
// Pets are loaded dynamically based on store selection; no pre-load needed.
customerRepository.getCustomerDropdowns().observeForever(r -> {
observeOnce(customerRepository.getCustomerDropdowns(), r -> {
if (r != null && r.status == Resource.Status.SUCCESS && r.data != null) {
customerList.setValue(r.data);
}
});
storeRepository.getStoreDropdowns().observeForever(r -> {
observeOnce(storeRepository.getStoreDropdowns(), r -> {
if (r != null && r.status == Resource.Status.SUCCESS && r.data != null) {
storeList.setValue(r.data);
}
@@ -155,7 +156,7 @@ public class AdoptionDetailViewModel extends ViewModel {
}
private void loadAvailablePetsByStore(Long storeId) {
petRepository.getAvailablePetsByStore(storeId).observeForever(r -> {
observeOnce(petRepository.getAvailablePetsByStore(storeId), r -> {
if (r != null && r.status == Resource.Status.SUCCESS && r.data != null) {
List<DropdownDTO> dropdowns = new ArrayList<>();
for (com.example.petstoremobile.dtos.PetDTO pet : r.data.getContent()) {
@@ -167,7 +168,7 @@ public class AdoptionDetailViewModel extends ViewModel {
}
private void loadPetPrice(Long petId) {
petRepository.getPetById(petId).observeForever(r -> {
observeOnce(petRepository.getPetById(petId), r -> {
if (r != null && r.status == Resource.Status.SUCCESS && r.data != null) {
com.example.petstoremobile.dtos.PetDTO pet = r.data;
// In edit mode, add the pet to the list so the spinner can display its name
@@ -185,7 +186,7 @@ public class AdoptionDetailViewModel extends ViewModel {
}
private void loadEmployeesForStore(Long storeId) {
storeRepository.getStoreEmployees(storeId).observeForever(r -> {
observeOnce(storeRepository.getStoreEmployees(storeId), r -> {
if (r != null && r.status == Resource.Status.SUCCESS && r.data != null) {
employeeList.setValue(r.data);
}
@@ -217,6 +218,10 @@ public class AdoptionDetailViewModel extends ViewModel {
s.isEmployeeEnabled = true;
s.isDateEnabled = true;
s.isStatusEnabled = true;
} else {
// Date cleared: disable everything except the date field so user can pick again
setAllEditableFieldsEnabled(s, false);
s.isDateEnabled = true;
}
});
}
@@ -240,7 +245,7 @@ public class AdoptionDetailViewModel extends ViewModel {
public LiveData<Resource<AdoptionDTO>> loadAdoption() {
MutableLiveData<Resource<AdoptionDTO>> result = new MutableLiveData<>();
adoptionRepository.getAdoptionById(adoptionId).observeForever(resource -> {
observeOnce(adoptionRepository.getAdoptionById(adoptionId), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
AdoptionDTO a = resource.data;
String formattedStatus = DateTimeUtils.formatStatusFromBackend(
@@ -321,6 +326,21 @@ public class AdoptionDetailViewModel extends ViewModel {
void run(T target);
}
/**
* Observes a LiveData once, removing the observer after the first response.
* */
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
public static class ViewState {
public boolean isEditing = false;
public boolean isAdoptionIdVisible = false;

View File

@@ -11,6 +11,8 @@ import com.example.petstoremobile.repositories.AdoptionRepository;
import com.example.petstoremobile.repositories.StoreRepository;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import java.util.ArrayList;
import java.util.List;
@@ -53,7 +55,7 @@ public class AdoptionListViewModel extends ViewModel {
if ("All Statuses".equals(status)) status = null;
isLoading.setValue(true);
adoptionRepository.getAllAdoptions(currentPage, PAGE_SIZE, query, status, storeId, date, employeeId).observeForever(resource -> {
observeOnce(adoptionRepository.getAllAdoptions(currentPage, PAGE_SIZE, query, status, storeId, date, employeeId), resource -> {
if (resource != null) {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
List<AdoptionDTO> currentList = reset ? new ArrayList<>() : new ArrayList<>(adoptions.getValue());
@@ -70,13 +72,25 @@ public class AdoptionListViewModel extends ViewModel {
}
public void loadStores() {
storeRepository.getAllStores(0, 100).observeForever(resource -> {
observeOnce(storeRepository.getAllStores(0, 100), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
stores.setValue(resource.data.getContent());
}
});
}
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
public LiveData<Resource<Void>> bulkDeleteAdoptions(List<String> ids) {
return adoptionRepository.bulkDeleteAdoptions(new BulkDeleteRequest(ids));
}

View File

@@ -8,6 +8,8 @@ import com.example.petstoremobile.dtos.SaleDTO;
import com.example.petstoremobile.repositories.SaleRepository;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
@@ -49,7 +51,7 @@ public class AnalyticsViewModel extends ViewModel {
public void loadAnalytics() {
isLoading.setValue(true);
errorMessage.setValue(null);
saleRepository.getAllSales(0, 2000, null, null, null, null, "saleDate,desc").observeForever(resource -> {
observeOnce(saleRepository.getAllSales(0, 2000, null, null, null, null, "saleDate,desc"), resource -> {
if (resource != null) {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
cachedSales = resource.data.getContent();
@@ -247,6 +249,18 @@ public class AnalyticsViewModel extends ViewModel {
return "Daily Revenue (" + s + " " + e + ")";
}
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
public static class FilterState {
public String startDate = "";
public String endDate = "";

View File

@@ -15,6 +15,8 @@ import com.example.petstoremobile.repositories.StoreRepository;
import com.example.petstoremobile.utils.DateTimeUtils;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import java.util.ArrayList;
import java.util.List;
@@ -71,13 +73,13 @@ public class AppointmentDetailViewModel extends ViewModel {
* Loads initial dropdown data for customers, stores, and services.
*/
public void loadInitialFormData() {
customerRepository.getCustomerDropdowns().observeForever(r -> {
observeOnce(customerRepository.getCustomerDropdowns(), r -> {
if (r != null && r.status == Resource.Status.SUCCESS) customers.setValue(r.data);
});
storeRepository.getStoreDropdowns().observeForever(r -> {
observeOnce(storeRepository.getStoreDropdowns(), r -> {
if (r != null && r.status == Resource.Status.SUCCESS) stores.setValue(r.data);
});
serviceRepository.getAllServices(0, 200, null, "serviceName").observeForever(r -> {
observeOnce(serviceRepository.getAllServices(0, 200, null, "serviceName"), r -> {
if (r != null && r.status == Resource.Status.SUCCESS && r.data != null) services.setValue(r.data.getContent());
});
}
@@ -206,7 +208,7 @@ public class AppointmentDetailViewModel extends ViewModel {
* Loads the list of pets for a specific customer.
*/
private void loadPetsForCustomer(Long customerId) {
petRepository.getCustomerPets(customerId).observeForever(r -> {
observeOnce(petRepository.getCustomerPets(customerId), r -> {
if (r != null && r.status == Resource.Status.SUCCESS) customerPets.setValue(r.data);
});
}
@@ -215,7 +217,7 @@ public class AppointmentDetailViewModel extends ViewModel {
* Loads the list of employees for a specific store.
*/
private void loadEmployeesForStore(Long storeId) {
storeRepository.getStoreEmployees(storeId).observeForever(r -> {
observeOnce(storeRepository.getStoreEmployees(storeId), r -> {
if (r != null && r.status == Resource.Status.SUCCESS) storeEmployees.setValue(r.data);
});
}
@@ -227,7 +229,7 @@ public class AppointmentDetailViewModel extends ViewModel {
*/
public LiveData<Resource<AppointmentDTO>> loadAppointment() {
MutableLiveData<Resource<AppointmentDTO>> result = new MutableLiveData<>();
repository.getAppointmentById(appointmentId).observeForever(resource -> {
observeOnce(repository.getAppointmentById(appointmentId), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
AppointmentDTO a = resource.data;
isOriginallyCancel = "CANCELLED".equalsIgnoreCase(a.getAppointmentStatus());
@@ -385,6 +387,19 @@ public class AppointmentDetailViewModel extends ViewModel {
void run(T t);
}
/** Observes a LiveData once, removing the observer after the first non-loading response. */
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
/**
* A Class to show the states of Appointment Detail Fragment.
*/

View File

@@ -11,6 +11,8 @@ import com.example.petstoremobile.repositories.AppointmentRepository;
import com.example.petstoremobile.repositories.StoreRepository;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import java.util.ArrayList;
import java.util.List;
@@ -39,7 +41,7 @@ public class AppointmentListViewModel extends ViewModel {
public void loadAppointments(String query, String status, Long storeId, String date, Long employeeId) {
isLoading.setValue(true);
appointmentRepository.getAllAppointments(0, 500, query, status, storeId, date, employeeId).observeForever(resource -> {
observeOnce(appointmentRepository.getAllAppointments(0, 500, query, status, storeId, date, employeeId), resource -> {
if (resource != null) {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
appointments.setValue(resource.data.getContent());
@@ -52,13 +54,25 @@ public class AppointmentListViewModel extends ViewModel {
}
public void loadStores() {
storeRepository.getAllStores(0, 100).observeForever(resource -> {
observeOnce(storeRepository.getAllStores(0, 100), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
stores.setValue(resource.data.getContent());
}
});
}
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
public LiveData<Resource<Void>> bulkDeleteAppointments(List<String> ids) {
return appointmentRepository.bulkDeleteAppointments(new BulkDeleteRequest(ids));
}

View File

@@ -9,6 +9,8 @@ import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.repositories.CouponRepository;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import java.util.ArrayList;
import java.util.List;
@@ -32,7 +34,7 @@ public class CouponListViewModel extends ViewModel {
public void loadCoupons(int page, int size, Boolean active, String discountType, String sort) {
isLoading.setValue(true);
repository.getAllCoupons(page, size, active, discountType, sort).observeForever(resource -> {
observeOnce(repository.getAllCoupons(page, size, active, discountType, sort), resource -> {
if (resource != null) {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
coupons.setValue(resource.data.getContent());
@@ -44,6 +46,18 @@ public class CouponListViewModel extends ViewModel {
});
}
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
public LiveData<Resource<Void>> bulkDeleteCoupons(List<Long> ids) {
return repository.bulkDeleteCoupons(ids);
}

View File

@@ -8,6 +8,8 @@ import com.example.petstoremobile.dtos.CustomerDTO;
import com.example.petstoremobile.repositories.CustomerRepository;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import java.util.ArrayList;
import java.util.List;
@@ -36,7 +38,7 @@ public class CustomerListViewModel extends ViewModel {
public void loadCustomers() {
isLoading.setValue(true);
repository.getAllCustomers(0, 200).observeForever(resource -> {
observeOnce(repository.getAllCustomers(0, 200), resource -> {
if (resource != null) {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
customers.setValue(resource.data.getContent());
@@ -49,6 +51,18 @@ public class CustomerListViewModel extends ViewModel {
});
}
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
public void filter(String query, String status) {
this.lastQuery = query;
this.lastStatus = status;

View File

@@ -11,6 +11,8 @@ import com.example.petstoremobile.repositories.InventoryRepository;
import com.example.petstoremobile.repositories.StoreRepository;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import java.util.ArrayList;
import java.util.List;
@@ -51,7 +53,7 @@ public class InventoryListViewModel extends ViewModel {
}
isLoading.setValue(true);
inventoryRepository.getAllInventory(query, storeId, currentPage, PAGE_SIZE, "product.prodName").observeForever(resource -> {
observeOnce(inventoryRepository.getAllInventory(query, storeId, currentPage, PAGE_SIZE, "product.prodName"), resource -> {
if (resource != null) {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
List<InventoryDTO> currentList = reset ? new ArrayList<>() : new ArrayList<>(inventory.getValue());
@@ -68,13 +70,25 @@ public class InventoryListViewModel extends ViewModel {
}
public void loadStores() {
storeRepository.getAllStores(0, 100).observeForever(resource -> {
observeOnce(storeRepository.getAllStores(0, 100), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
stores.setValue(resource.data.getContent());
}
});
}
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
public LiveData<Resource<Void>> bulkDeleteInventory(List<String> ids) {
return inventoryRepository.bulkDeleteInventory(new BulkDeleteRequest(ids));
}

View File

@@ -11,6 +11,8 @@ import com.example.petstoremobile.repositories.PetRepository;
import com.example.petstoremobile.repositories.StoreRepository;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import java.util.ArrayList;
import java.util.List;
@@ -45,13 +47,13 @@ public class PetDetailViewModel extends ViewModel {
}
public void loadInitialFormData() {
customerRepository.getCustomerDropdowns().observeForever(resource -> {
observeOnce(customerRepository.getCustomerDropdowns(), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
customerList.setValue(resource.data);
}
});
storeRepository.getStoreDropdowns().observeForever(resource -> {
observeOnce(storeRepository.getStoreDropdowns(), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
storeList.setValue(resource.data);
}
@@ -134,7 +136,7 @@ public class PetDetailViewModel extends ViewModel {
public LiveData<Resource<PetDTO>> loadPet() {
MutableLiveData<Resource<PetDTO>> result = new MutableLiveData<>();
petRepository.getPetById(petId).observeForever(resource -> {
observeOnce(petRepository.getPetById(petId), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
PetDTO pet = resource.data;
selectedCustomerId = pet.getCustomerId();
@@ -227,6 +229,17 @@ public class PetDetailViewModel extends ViewModel {
void run(T target);
}
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
public static class ViewState {
public boolean isEditing = false;

View File

@@ -12,6 +12,8 @@ import com.example.petstoremobile.repositories.PetRepository;
import com.example.petstoremobile.repositories.StoreRepository;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import java.util.ArrayList;
import java.util.List;
@@ -43,7 +45,7 @@ public class PetListViewModel extends ViewModel {
if ("All Species".equals(species)) species = null;
isLoading.setValue(true);
petRepository.getAllPets(0, 100, query, status, species, storeId, null, "petName").observeForever(resource -> {
observeOnce(petRepository.getAllPets(0, 100, query, status, species, storeId, null, "petName"), resource -> {
if (resource != null) {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
pets.setValue(resource.data.getContent());
@@ -56,13 +58,25 @@ public class PetListViewModel extends ViewModel {
}
public void loadStores() {
storeRepository.getAllStores(0, 100).observeForever(resource -> {
observeOnce(storeRepository.getAllStores(0, 100), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
stores.setValue(resource.data.getContent());
}
});
}
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
public LiveData<Resource<Void>> bulkDeletePets(List<String> ids) {
return petRepository.bulkDeletePets(new BulkDeleteRequest(ids));
}

View File

@@ -10,6 +10,8 @@ import com.example.petstoremobile.repositories.CategoryRepository;
import com.example.petstoremobile.repositories.ProductRepository;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import java.util.ArrayList;
import java.util.List;
@@ -38,7 +40,7 @@ public class ProductListViewModel extends ViewModel {
public void loadProducts(String query, Long categoryId) {
isLoading.setValue(true);
productRepository.getAllProducts(query, categoryId, 0, 100, "prodName").observeForever(resource -> {
observeOnce(productRepository.getAllProducts(query, categoryId, 0, 100, "prodName"), resource -> {
if (resource != null) {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
products.setValue(resource.data.getContent());
@@ -51,10 +53,22 @@ public class ProductListViewModel extends ViewModel {
}
public void loadCategories() {
productRepository.getCategoryDropdowns().observeForever(resource -> {
observeOnce(productRepository.getCategoryDropdowns(), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
categories.setValue(resource.data);
}
});
}
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
}

View File

@@ -13,6 +13,8 @@ import com.example.petstoremobile.repositories.ProductSupplierRepository;
import com.example.petstoremobile.repositories.SupplierRepository;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import java.util.ArrayList;
import java.util.List;
@@ -45,7 +47,7 @@ public class ProductSupplierListViewModel extends ViewModel {
public void loadProductSuppliers(String query, Long productId, Long supplierId) {
isLoading.setValue(true);
psRepository.getAllProductSuppliers(0, 100, query, productId, supplierId, "productName").observeForever(resource -> {
observeOnce(psRepository.getAllProductSuppliers(0, 100, query, productId, supplierId, "productName"), resource -> {
if (resource != null) {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
productSuppliers.setValue(resource.data.getContent());
@@ -58,19 +60,31 @@ public class ProductSupplierListViewModel extends ViewModel {
}
public void loadFilterData() {
productRepository.getAllProducts(null, null, 0, 100, "prodName").observeForever(resource -> {
observeOnce(productRepository.getAllProducts(null, null, 0, 100, "prodName"), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
products.setValue(resource.data.getContent());
}
});
supplierRepository.getAllSuppliers(0, 100, null, "supCompany").observeForever(resource -> {
observeOnce(supplierRepository.getAllSuppliers(0, 100, null, "supCompany"), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
suppliers.setValue(resource.data.getContent());
}
});
}
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
public LiveData<Resource<Void>> bulkDeleteProductSuppliers(List<String> ids) {
return psRepository.bulkDeleteProductSuppliers(new BulkDeleteRequest(ids));
}

View File

@@ -10,6 +10,8 @@ import com.example.petstoremobile.repositories.PurchaseOrderRepository;
import com.example.petstoremobile.repositories.StoreRepository;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import java.util.ArrayList;
import java.util.List;
@@ -38,7 +40,7 @@ public class PurchaseOrderListViewModel extends ViewModel {
public void loadPurchaseOrders(String query, Long storeId) {
isLoading.setValue(true);
purchaseOrderRepository.getAllPurchaseOrders(0, 100, query, storeId, "purchaseOrderId,desc").observeForever(resource -> {
observeOnce(purchaseOrderRepository.getAllPurchaseOrders(0, 100, query, storeId, "purchaseOrderId,desc"), resource -> {
if (resource != null) {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
purchaseOrders.setValue(resource.data.getContent());
@@ -51,10 +53,22 @@ public class PurchaseOrderListViewModel extends ViewModel {
}
public void loadStores() {
storeRepository.getAllStores(0, 100).observeForever(resource -> {
observeOnce(storeRepository.getAllStores(0, 100), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
stores.setValue(resource.data.getContent());
}
});
}
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
}

View File

@@ -11,6 +11,8 @@ import com.example.petstoremobile.repositories.SaleRepository;
import com.example.petstoremobile.repositories.StoreRepository;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import java.util.ArrayList;
import java.util.List;
@@ -51,7 +53,7 @@ public class SaleListViewModel extends ViewModel {
}
isLoading.setValue(true);
saleRepository.getAllSales(currentPage, PAGE_SIZE, query, paymentMethod, storeId, isRefund, "saleDate,desc").observeForever(resource -> {
observeOnce(saleRepository.getAllSales(currentPage, PAGE_SIZE, query, paymentMethod, storeId, isRefund, "saleDate,desc"), resource -> {
if (resource != null) {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
List<SaleDTO> currentList = reset ? new ArrayList<>() : new ArrayList<>(sales.getValue());
@@ -68,10 +70,22 @@ public class SaleListViewModel extends ViewModel {
}
public void loadStores() {
storeRepository.getAllStores(0, 100).observeForever(resource -> {
observeOnce(storeRepository.getAllStores(0, 100), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
stores.setValue(resource.data.getContent());
}
});
}
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
}

View File

@@ -8,6 +8,8 @@ import com.example.petstoremobile.dtos.ServiceDTO;
import com.example.petstoremobile.repositories.ServiceRepository;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import javax.inject.Inject;
import dagger.hilt.android.lifecycle.HiltViewModel;
@@ -55,7 +57,7 @@ public class ServiceDetailViewModel extends ViewModel {
public LiveData<Resource<ServiceDTO>> loadService() {
MutableLiveData<Resource<ServiceDTO>> result = new MutableLiveData<>();
repository.getServiceById(serviceId).observeForever(resource -> {
observeOnce(repository.getServiceById(serviceId), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
ServiceDTO service = resource.data;
updateViewState(state -> {
@@ -106,6 +108,18 @@ public class ServiceDetailViewModel extends ViewModel {
void run(T target);
}
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
public static class ViewState {
public boolean isEditing = false;
public boolean isDeleteVisible = false;

View File

@@ -10,6 +10,8 @@ import com.example.petstoremobile.dtos.ServiceDTO;
import com.example.petstoremobile.repositories.ServiceRepository;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import java.util.ArrayList;
import java.util.List;
@@ -46,7 +48,7 @@ public class ServiceListViewModel extends ViewModel {
}
isLoading.setValue(true);
repository.getAllServices(currentPage, PAGE_SIZE, query, "serviceName").observeForever(resource -> {
observeOnce(repository.getAllServices(currentPage, PAGE_SIZE, query, "serviceName"), resource -> {
if (resource != null) {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
List<ServiceDTO> currentList = reset ? new ArrayList<>() : new ArrayList<>(services.getValue());
@@ -62,6 +64,18 @@ public class ServiceListViewModel extends ViewModel {
});
}
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
public LiveData<Resource<Void>> bulkDeleteServices(List<String> ids) {
return repository.bulkDeleteServices(new BulkDeleteRequest(ids));
}

View File

@@ -10,6 +10,8 @@ import com.example.petstoremobile.repositories.EmployeeRepository;
import com.example.petstoremobile.repositories.StoreRepository;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import java.util.ArrayList;
import java.util.List;
@@ -42,7 +44,7 @@ public class StaffListViewModel extends ViewModel {
public void loadStaff() {
isLoading.setValue(true);
repository.getAllEmployees(0, 100).observeForever(resource -> {
observeOnce(repository.getAllEmployees(0, 100), resource -> {
if (resource != null) {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
employees.setValue(resource.data.getContent());
@@ -56,13 +58,25 @@ public class StaffListViewModel extends ViewModel {
}
public void loadStores() {
storeRepository.getAllStores(0, 100).observeForever(resource -> {
observeOnce(storeRepository.getAllStores(0, 100), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
stores.setValue(resource.data.getContent());
}
});
}
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
public void filter(String query, Long storeId, String status) {
this.lastQuery = query;
this.lastStoreId = storeId;

View File

@@ -8,6 +8,8 @@ import com.example.petstoremobile.dtos.SupplierDTO;
import com.example.petstoremobile.repositories.SupplierRepository;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import javax.inject.Inject;
import dagger.hilt.android.lifecycle.HiltViewModel;
@@ -55,7 +57,7 @@ public class SupplierDetailViewModel extends ViewModel {
public LiveData<Resource<SupplierDTO>> loadSupplier() {
MutableLiveData<Resource<SupplierDTO>> result = new MutableLiveData<>();
repository.getSupplierById(supId).observeForever(resource -> {
observeOnce(repository.getSupplierById(supId), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
SupplierDTO s = resource.data;
updateViewState(state -> {
@@ -99,6 +101,18 @@ public class SupplierDetailViewModel extends ViewModel {
void run(T target);
}
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
public static class ViewState {
public boolean isEditing = false;
public boolean isDeleteVisible = false;

View File

@@ -9,6 +9,8 @@ import com.example.petstoremobile.dtos.SupplierDTO;
import com.example.petstoremobile.repositories.SupplierRepository;
import com.example.petstoremobile.utils.Resource;
import androidx.lifecycle.Observer;
import java.util.ArrayList;
import java.util.List;
@@ -33,7 +35,7 @@ public class SupplierListViewModel extends ViewModel {
public void loadSuppliers(String query) {
isLoading.setValue(true);
repository.getAllSuppliers(0, 100, query, "supCompany").observeForever(resource -> {
observeOnce(repository.getAllSuppliers(0, 100, query, "supCompany"), resource -> {
if (resource != null) {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
suppliers.setValue(resource.data.getContent());
@@ -45,6 +47,18 @@ public class SupplierListViewModel extends ViewModel {
});
}
private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
liveData.observeForever(new Observer<Resource<T>>() {
@Override
public void onChanged(Resource<T> resource) {
if (resource == null || resource.status != Resource.Status.LOADING) {
liveData.removeObserver(this);
}
handler.onChanged(resource);
}
});
}
public LiveData<Resource<Void>> bulkDeleteSuppliers(List<String> ids) {
return repository.bulkDeleteSuppliers(new BulkDeleteRequest(ids));
}