Кашина_РМП_ЛБ17_6
.docxМинистерство науки и высшего образования Российской Федерации Федеральное государственное бюджетное образовательное учреждение высшего образования
«Владимирский государственный университет
имени Александра Григорьевича и Николая Григорьевича Столетовых» (ВлГУ)
Колледж инновационных технологий и предпринимательства
КАФЕДРА ФИЗИКИ И ПРИКЛАДНОЙ МАТЕМАТИКИ
Лабораторная работа № 17_6
по МДК 01.03 «Разработка мобильных приложений»
на тему: «Использование БД в Android»
Выполнил
студент группы ИПсп-123
Кашина Д. А.
Принял
Красильщикова В.В.
Владимир, 2026 г.
Цель работы: научится реализовывать собственное мобильное приложение в андроид.
Ход работы: создать мобильное приложение с использованием БД, согласно варианту.
AppDatabase.java
package com.example.magnitcosmeticdata; import android.content.Context; import androidx.room.Database; import androidx.room.Room; import androidx.room.RoomDatabase; @Database(entities = {Product.class}, version = 1, exportSchema = false) public abstract class AppDatabase extends RoomDatabase { private static AppDatabase instance; public abstract ProductDao productDao(); public static synchronized AppDatabase getInstance(Context context) { if (instance == null) { instance = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "magnit_cosmetic_db") .fallbackToDestructiveMigration() .build(); } return instance; } }
DatabaseInitalizer.java
package com.example.magnitcosmeticdata; import android.os.AsyncTask; public class DatabaseInitializer { public static void populateDatabase(final AppDatabase db) { new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... voids) { insertProducts(db); return null; } }.execute(); } private static void insertProducts(AppDatabase db) { Product[] products = { new Product("Тональный крем", 850.0, "2024-01-15", "L'Oreal", "мл", 450.0), new Product("Тушь для ресниц", 450.0, "2024-02-10", "Maybelline", "шт", 250.0), new Product("Помада", 350.0, "2024-01-20", "Avon", "шт", 180.0), new Product("Лак для ногтей", 120.0, "2024-03-01", "Essie", "мл", 70.0), new Product("Мицеллярная вода", 300.0, "2024-02-05", "Garnier", "мл", 200.0), new Product("Сыворотка для лица", 1200.0, "2024-01-10", "Vichy", "мл", 800.0), new Product("Крем для рук", 180.0, "2024-03-15", "Nivea", "мл", 100.0), new Product("Пудра", 520.0, "2024-02-20", "Pupa", "г", 320.0), new Product("Хайлайтер", 670.0, "2024-01-25", "NYX", "г", 420.0), new Product("Праймер", 950.0, "2024-03-10", "Smashbox", "мл", 600.0) }; for (Product p : products) { db.productDao().insert(p); } } }
FilterFragment.java
package com.example.magnitcosmeticdata; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; public class FilterFragment extends Fragment { private ProductViewModel viewModel; private ProductAdapterSimple adapter; // ← изменено на простой адаптер private TextView tvCountFilter; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_filter, container, false); RecyclerView recyclerView = view.findViewById(R.id.recyclerViewFilter); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); adapter = new ProductAdapterSimple(); // ← простой адаптер recyclerView.setAdapter(adapter); EditText etMinCost = view.findViewById(R.id.etMinCost); Button btnFilter = view.findViewById(R.id.btnFilter); tvCountFilter = view.findViewById(R.id.tvCountFilter); viewModel = new ViewModelProvider(requireActivity()).get(ProductViewModel.class); btnFilter.setOnClickListener(v -> { String input = etMinCost.getText().toString(); if (!input.isEmpty()) { double minCost = Double.parseDouble(input); viewModel.getProductsWithCostGreaterThan(minCost).observe(getViewLifecycleOwner(), products -> { adapter.setProducts(products); tvCountFilter.setText("📊 Найдено товаров с ценой > " + minCost + ": " + products.size()); Toast.makeText(getContext(), "Товаров с ценой > " + minCost + ": " + products.size(), Toast.LENGTH_SHORT).show(); }); } else { Toast.makeText(getContext(), "Введите значение", Toast.LENGTH_SHORT).show(); } }); return view; } }
GroupByManufacturer.java
package com.example.magnitcosmeticdata; public class GroupByManufacturer { private String manufacturer; private int count; private double avgCost; public GroupByManufacturer(String manufacturer, int count, double avgCost) { this.manufacturer = manufacturer; this.count = count; this.avgCost = avgCost; } public String getManufacturer() { return manufacturer; } public int getCount() { return count; } public double getAvgCost() { return avgCost; } }
GroupByUnit.java
package com.example.magnitcosmeticdata; public class GroupByUnit { private String unit; private int count; private double avgCost; public GroupByUnit(String unit, int count, double avgCost) { this.unit = unit; this.count = count; this.avgCost = avgCost; } public String getUnit() { return unit; } public int getCount() { return count; } public double getAvgCost() { return avgCost; } }
GroupFragment,java
package com.example.magnitcosmeticdata; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; public class GroupFragment extends Fragment { private ProductViewModel viewModel; private TextView tvGroupResult; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_group, container, false); tvGroupResult = view.findViewById(R.id.tvGroupResult); Button btnGroupManufacturer = view.findViewById(R.id.btnGroupManufacturer); Button btnGroupUnit = view.findViewById(R.id.btnGroupUnit); viewModel = new ViewModelProvider(requireActivity()).get(ProductViewModel.class); btnGroupManufacturer.setOnClickListener(v -> { viewModel.getGroupByManufacturer().observe(getViewLifecycleOwner(), groups -> { StringBuilder sb = new StringBuilder("Группировка по производителю:\n\n"); for (GroupByManufacturer group : groups) { sb.append("📦 ").append(group.getManufacturer()) .append("\n Количество: ").append(group.getCount()) .append("\n Средняя цена: ").append(String.format("%.2f", group.getAvgCost())) .append(" ₽\n\n"); } tvGroupResult.setText(sb.toString()); }); }); btnGroupUnit.setOnClickListener(v -> { viewModel.getGroupByUnit().observe(getViewLifecycleOwner(), groups -> { StringBuilder sb = new StringBuilder("Группировка по единице измерения:\n\n"); for (GroupByUnit group : groups) { sb.append("📏 ").append(group.getUnit()) .append("\n Количество: ").append(group.getCount()) .append("\n Средняя цена: ").append(String.format("%.2f", group.getAvgCost())) .append(" ₽\n\n"); } tvGroupResult.setText(sb.toString()); }); }); return view; } }
ListFragment.java
package com.example.magnitcosmeticdata; import android.os.Bundle; import android.widget.Toast; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; public class ListFragment extends Fragment implements ProductAdapter.OnProductClickListener { private ProductViewModel viewModel; private ProductAdapter adapter; private Button btnAdd; private TextView tvCount; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_list, container, false); RecyclerView recyclerView = view.findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); adapter = new ProductAdapter(); adapter.setOnProductClickListener(this); recyclerView.setAdapter(adapter); btnAdd = view.findViewById(R.id.btnAdd); tvCount = view.findViewById(R.id.tvCount); btnAdd.setOnClickListener(v -> { ProductDialog.newInstanceForAdd().show(getChildFragmentManager(), "AddDialog"); }); viewModel = new ViewModelProvider(requireActivity()).get(ProductViewModel.class); viewModel.getAllProducts().observe(getViewLifecycleOwner(), products -> { adapter.setProducts(products); tvCount.setText("📊 Всего товаров: " + products.size()); }); return view; } @Override public void onEditClick(Product product) { ProductDialog.newInstanceForEdit(product).show(getChildFragmentManager(), "EditDialog"); } @Override public void onDeleteClick(Product product) { new androidx.appcompat.app.AlertDialog.Builder(getContext()) .setTitle("Удаление") .setMessage("Вы уверены, что хотите удалить товар \"" + product.getName() + "\"?") .setPositiveButton("Да", (dialog, which) -> { viewModel.delete(product); Toast.makeText(getContext(), "Товар удален", Toast.LENGTH_SHORT).show(); }) .setNegativeButton("Нет", null) .show(); } }
MainActivity.java
package com.example.magnitcosmeticdata; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Инициализация БД AppDatabase db = AppDatabase.getInstance(this); DatabaseInitializer.populateDatabase(db); // Загрузка начального фрагмента if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() .replace(R.id.nav_host_fragment, new ListFragment()) .commit(); } // Bottom Navigation findViewById(R.id.bottomNavigation).setOnClickListener(v -> {}); com.google.android.material.bottomnavigation.BottomNavigationView bottomNav = findViewById(R.id.bottomNavigation); bottomNav.setOnItemSelectedListener(item -> { Fragment selectedFragment = null; int itemId = item.getItemId(); if (itemId == R.id.nav_list) { selectedFragment = new ListFragment(); } else if (itemId == R.id.nav_sort) { selectedFragment = new SortFragment(); } else if (itemId == R.id.nav_group) { selectedFragment = new GroupFragment(); } else if (itemId == R.id.nav_stats) { selectedFragment = new StatsFragment(); } else if (itemId == R.id.nav_filter) { selectedFragment = new FilterFragment(); } if (selectedFragment != null) { getSupportFragmentManager().beginTransaction() .replace(R.id.nav_host_fragment, selectedFragment) .commit(); } return true; }); } }
Product.java
package com.example.magnitcosmeticdata; import androidx.room.Entity; import androidx.room.PrimaryKey; import java.io.Serializable; @Entity(tableName = "products") public class Product implements Serializable { @PrimaryKey(autoGenerate = true) private int id; private String name; private double cost; private String releaseDate; private String manufacturer; private String unit; private double supplierPrice; public Product() {} public Product(String name, double cost, String releaseDate, String manufacturer, String unit, double supplierPrice) { this.name = name; this.cost = cost; this.releaseDate = releaseDate; this.manufacturer = manufacturer; this.unit = unit; this.supplierPrice = supplierPrice; } // Getters public int getId() { return id; } public String getName() { return name; } public double getCost() { return cost; } public String getReleaseDate() { return releaseDate; } public String getManufacturer() { return manufacturer; } public String getUnit() { return unit; } public double getSupplierPrice() { return supplierPrice; } // Setters public void setId(int id) { this.id = id; } public void setName(String name) { this.name = name; } public void setCost(double cost) { this.cost = cost; } public void setReleaseDate(String releaseDate) { this.releaseDate = releaseDate; } public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; } public void setUnit(String unit) { this.unit = unit; } public void setSupplierPrice(double supplierPrice) { this.supplierPrice = supplierPrice; } }
ProductAdapter.java
package com.example.magnitcosmeticdata; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageButton; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; import java.util.List; public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ProductViewHolder> { private List<Product> products = new ArrayList<>(); private OnProductClickListener listener; public interface OnProductClickListener { void onEditClick(Product product); void onDeleteClick(Product product); } public void setOnProductClickListener(OnProductClickListener listener) { this.listener = listener; } @NonNull @Override public ProductViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_product, parent, false); return new ProductViewHolder(view); } @Override public void onBindViewHolder(@NonNull ProductViewHolder holder, int position) { Product product = products.get(position); holder.tvName.setText(product.getName()); holder.tvManufacturer.setText("Производитель: " + product.getManufacturer()); holder.tvCost.setText(String.format("Цена: %.2f ₽", product.getCost())); holder.tvSupplierPrice.setText(String.format("Цена поставщика: %.2f ₽", product.getSupplierPrice())); holder.tvUnit.setText("Ед.изм: " + product.getUnit()); holder.tvDate.setText("Дата выпуска: " + product.getReleaseDate()); holder.btnEdit.setOnClickListener(v -> { if (listener != null) listener.onEditClick(product); }); holder.btnDelete.setOnClickListener(v -> { if (listener != null) listener.onDeleteClick(product); }); } @Override public int getItemCount() { return products.size(); } public void setProducts(List<Product> products) { this.products = products; notifyDataSetChanged(); } static class ProductViewHolder extends RecyclerView.ViewHolder { TextView tvName, tvManufacturer, tvCost, tvSupplierPrice, tvUnit, tvDate; ImageButton btnEdit, btnDelete; ProductViewHolder(@NonNull View itemView) { super(itemView); tvName = itemView.findViewById(R.id.tvName); tvManufacturer = itemView.findViewById(R.id.tvManufacturer); tvCost = itemView.findViewById(R.id.tvCost); tvSupplierPrice = itemView.findViewById(R.id.tvSupplierPrice); tvUnit = itemView.findViewById(R.id.tvUnit); tvDate = itemView.findViewById(R.id.tvDate); btnEdit = itemView.findViewById(R.id.btnEdit); btnDelete = itemView.findViewById(R.id.btnDelete); } } }
ProductAdapterSimple.java
package com.example.magnitcosmeticdata; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; import java.util.List; public class ProductAdapterSimple extends RecyclerView.Adapter<ProductAdapterSimple.ProductViewHolder> { private List<Product> products = new ArrayList<>(); @NonNull @Override public ProductViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_product_simple, parent, false); return new ProductViewHolder(view); } @Override public void onBindViewHolder(@NonNull ProductViewHolder holder, int position) { Product product = products.get(position); holder.tvName.setText(product.getName()); holder.tvManufacturer.setText("Производитель: " + product.getManufacturer()); holder.tvCost.setText(String.format("Цена: %.2f ₽", product.getCost())); holder.tvSupplierPrice.setText(String.format("Цена поставщика: %.2f ₽", product.getSupplierPrice())); holder.tvUnit.setText("Ед.изм: " + product.getUnit()); holder.tvDate.setText("Дата выпуска: " + product.getReleaseDate()); } @Override public int getItemCount() { return products.size(); } public void setProducts(List<Product> products) { this.products = products; notifyDataSetChanged(); } static class ProductViewHolder extends RecyclerView.ViewHolder { TextView tvName, tvManufacturer, tvCost, tvSupplierPrice, tvUnit, tvDate; ProductViewHolder(@NonNull View itemView) { super(itemView); tvName = itemView.findViewById(R.id.tvName); tvManufacturer = itemView.findViewById(R.id.tvManufacturer); tvCost = itemView.findViewById(R.id.tvCost); tvSupplierPrice = itemView.findViewById(R.id.tvSupplierPrice); tvUnit = itemView.findViewById(R.id.tvUnit); tvDate = itemView.findViewById(R.id.tvDate); } } }
ProductDao.java
package com.example.magnitcosmeticdata; import androidx.lifecycle.LiveData; import androidx.room.Dao; import androidx.room.Delete; import androidx.room.Insert; import androidx.room.Query; import androidx.room.Update; import java.util.List; @Dao public interface ProductDao { @Insert void insert(Product product); @Update void update(Product product); @Delete void delete(Product product); @Query("SELECT * FROM products") LiveData<List<Product>> getAll(); @Query("SELECT * FROM products ORDER BY cost ASC") LiveData<List<Product>> getAllSortedByCostAsc(); @Query("SELECT * FROM products ORDER BY cost DESC") LiveData<List<Product>> getAllSortedByCostDesc(); @Query("SELECT MAX(cost) FROM products") LiveData<Double> getMaxCost(); @Query("SELECT AVG(cost) FROM products") LiveData<Double> getAverageCost(); @Query("SELECT * FROM products WHERE cost > :minCost") LiveData<List<Product>> getProductsWithCostGreaterThan(double minCost); @Query("SELECT * FROM products WHERE cost < (SELECT AVG(cost) FROM products)") LiveData<List<Product>> getProductsWithCostLessThanAverage(); @Query("SELECT manufacturer, COUNT(*) as count, AVG(cost) as avgCost FROM products GROUP BY manufacturer") LiveData<List<GroupByManufacturer>> groupByManufacturer(); @Query("SELECT unit, COUNT(*) as count, AVG(cost) as avgCost FROM products GROUP BY unit") LiveData<List<GroupByUnit>> groupByUnit(); }
ProductDialog.java
package com.example.magnitcosmeticdata; import android.app.AlertDialog; import android.app.Dialog; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.DialogFragment; import androidx.lifecycle.ViewModelProvider; public class ProductDialog extends DialogFragment { private EditText etName, etCost, etReleaseDate, etManufacturer, etUnit, etSupplierPrice; private ProductViewModel viewModel; private Product productToEdit; private boolean isEditMode = false; public static ProductDialog newInstanceForAdd() { return new ProductDialog(); } public static ProductDialog newInstanceForEdit(Product product) { ProductDialog dialog = new ProductDialog(); Bundle args = new Bundle(); args.putSerializable("product", product); dialog.setArguments(args); return dialog; } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { productToEdit = (Product) getArguments().getSerializable("product"); if (productToEdit != null) { isEditMode = true; } } } @NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); LayoutInflater inflater = requireActivity().getLayoutInflater(); View view = inflater.inflate(R.layout.dialog_product, null); viewModel = new ViewModelProvider(requireActivity()).get(ProductViewModel.class); etName = view.findViewById(R.id.etName); etCost = view.findViewById(R.id.etCost); etReleaseDate = view.findViewById(R.id.etReleaseDate); etManufacturer = view.findViewById(R.id.etManufacturer); etUnit = view.findViewById(R.id.etUnit); etSupplierPrice = view.findViewById(R.id.etSupplierPrice); if (isEditMode && productToEdit != null) { etName.setText(productToEdit.getName()); etCost.setText(String.valueOf(productToEdit.getCost())); etReleaseDate.setText(productToEdit.getReleaseDate()); etManufacturer.setText(productToEdit.getManufacturer()); etUnit.setText(productToEdit.getUnit()); etSupplierPrice.setText(String.valueOf(productToEdit.getSupplierPrice())); } builder.setView(view) .setTitle(isEditMode ? "✏️ Редактировать товар" : "➕ Добавить товар") .setPositiveButton(isEditMode ? "Сохранить" : "Добавить", null) .setNegativeButton("Отмена", (dialog, which) -> dialog.dismiss()); AlertDialog dialog = builder.create(); dialog.setOnShowListener(dialogInterface -> { Button button = dialog.getButton(AlertDialog.BUTTON_POSITIVE); button.setOnClickListener(v -> { if (validateInputs()) { saveProduct(); dialog.dismiss(); } }); }); return dialog; } private boolean validateInputs() { if (etName.getText().toString().trim().isEmpty()) { Toast.makeText(getContext(), "Введите наименование", Toast.LENGTH_SHORT).show(); return false; } if (etCost.getText().toString().trim().isEmpty()) { Toast.makeText(getContext(), "Введите стоимость", Toast.LENGTH_SHORT).show(); return false; } if (etReleaseDate.getText().toString().trim().isEmpty()) { Toast.makeText(getContext(), "Введите дату выпуска", Toast.LENGTH_SHORT).show(); return false; } if (etManufacturer.getText().toString().trim().isEmpty()) { Toast.makeText(getContext(), "Введите производителя", Toast.LENGTH_SHORT).show(); return false; } if (etUnit.getText().toString().trim().isEmpty()) { Toast.makeText(getContext(), "Введите единицу измерения", Toast.LENGTH_SHORT).show(); return false; } if (etSupplierPrice.getText().toString().trim().isEmpty()) { Toast.makeText(getContext(), "Введите цену поставщика", Toast.LENGTH_SHORT).show(); return false; } return true; } private void saveProduct() { String name = etName.getText().toString().trim(); double cost = Double.parseDouble(etCost.getText().toString().trim()); String releaseDate = etReleaseDate.getText().toString().trim(); String manufacturer = etManufacturer.getText().toString().trim(); String unit = etUnit.getText().toString().trim(); double supplierPrice = Double.parseDouble(etSupplierPrice.getText().toString().trim()); if (isEditMode && productToEdit != null) { productToEdit.setName(name); productToEdit.setCost(cost); productToEdit.setReleaseDate(releaseDate); productToEdit.setManufacturer(manufacturer); productToEdit.setUnit(unit); productToEdit.setSupplierPrice(supplierPrice); viewModel.update(productToEdit); Toast.makeText(getContext(), "Товар обновлен", Toast.LENGTH_SHORT).show(); } else { Product newProduct = new Product(name, cost, releaseDate, manufacturer, unit, supplierPrice); viewModel.insert(newProduct); Toast.makeText(getContext(), "Товар добавлен", Toast.LENGTH_SHORT).show(); } } }
ProductViewModel.java
package com.example.magnitcosmeticdata; import android.app.Application; import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData; import java.util.List; public class ProductViewModel extends AndroidViewModel { private ProductDao productDao; private LiveData<List<Product>> allProducts; private LiveData<List<Product>> sortedByCostAsc; private LiveData<List<Product>> sortedByCostDesc; private LiveData<List<GroupByManufacturer>> groupByManufacturer; private LiveData<List<GroupByUnit>> groupByUnit; private LiveData<Double> maxCost; private LiveData<Double> averageCost; public ProductViewModel(Application application) { super(application); AppDatabase db = AppDatabase.getInstance(application); productDao = db.productDao(); allProducts = productDao.getAll(); sortedByCostAsc = productDao.getAllSortedByCostAsc(); sortedByCostDesc = productDao.getAllSortedByCostDesc(); groupByManufacturer = productDao.groupByManufacturer(); groupByUnit = productDao.groupByUnit(); maxCost = productDao.getMaxCost(); averageCost = productDao.getAverageCost(); } public LiveData<List<Product>> getAllProducts() { return allProducts; } public LiveData<List<Product>> getSortedByCostAsc() { return sortedByCostAsc; } public LiveData<List<Product>> getSortedByCostDesc() { return sortedByCostDesc; } public LiveData<List<GroupByManufacturer>> getGroupByManufacturer() { return groupByManufacturer; } public LiveData<List<GroupByUnit>> getGroupByUnit() { return groupByUnit; } public LiveData<Double> getMaxCost() { return maxCost; } public LiveData<Double> getAverageCost() { return averageCost; } public LiveData<List<Product>> getProductsWithCostGreaterThan(double minCost) { return productDao.getProductsWithCostGreaterThan(minCost); } public LiveData<List<Product>> getProductsLessThanAverage() { return productDao.getProductsWithCostLessThanAverage(); } // Добавьте эти методы в класс ProductViewModel public void insert(Product product) { new Thread(() -> productDao.insert(product)).start(); } public void update(Product product) { new Thread(() -> productDao.update(product)).start(); } public void delete(Product product) { new Thread(() -> productDao.delete(product)).start(); } }
SortFragment.java
package com.example.magnitcosmeticdata; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; public class SortFragment extends Fragment { private ProductViewModel viewModel; private ProductAdapterSimple adapter; // ← изменено на простой адаптер private TextView tvCount; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_sort, container, false); RecyclerView recyclerView = view.findViewById(R.id.recyclerViewSort); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); adapter = new ProductAdapterSimple(); // ← простой адаптер recyclerView.setAdapter(adapter); Button btnAsc = view.findViewById(R.id.btnSortAsc); Button btnDesc = view.findViewById(R.id.btnSortDesc); tvCount = view.findViewById(R.id.tvCountSort); viewModel = new ViewModelProvider(requireActivity()).get(ProductViewModel.class); btnAsc.setOnClickListener(v -> { viewModel.getSortedByCostAsc().observe(getViewLifecycleOwner(), products -> { adapter.setProducts(products); tvCount.setText("📊 Найдено товаров: " + products.size()); Toast.makeText(getContext(), "Сортировка по возрастанию цены", Toast.LENGTH_SHORT).show(); }); }); btnDesc.setOnClickListener(v -> { viewModel.getSortedByCostDesc().observe(getViewLifecycleOwner(), products -> { adapter.setProducts(products); tvCount.setText("📊 Найдено товаров: " + products.size()); Toast.makeText(getContext(), "Сортировка по убыванию цены", Toast.LENGTH_SHORT).show(); }); }); return view; } }
StatsFragment.java
package com.example.magnitcosmeticdata; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; public class StatsFragment extends Fragment { private ProductViewModel viewModel; private ProductAdapterSimple adapter; // ← изменено на простой адаптер private TextView tvCountLessThanAvg; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_stats, container, false); TextView tvMaxCost = view.findViewById(R.id.tvMaxCost); TextView tvAverageCost = view.findViewById(R.id.tvAverageCost); Button btnShowLessThanAverage = view.findViewById(R.id.btnShowLessThanAverage); tvCountLessThanAvg = view.findViewById(R.id.tvCountLessThanAvg); RecyclerView recyclerView = view.findViewById(R.id.recyclerViewLessThanAvg); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); adapter = new ProductAdapterSimple(); // ← простой адаптер recyclerView.setAdapter(adapter); viewModel = new ViewModelProvider(requireActivity()).get(ProductViewModel.class); viewModel.getMaxCost().observe(getViewLifecycleOwner(), max -> { tvMaxCost.setText(String.format("💰 Максимальная цена: %.2f ₽", max)); }); viewModel.getAverageCost().observe(getViewLifecycleOwner(), avg -> { tvAverageCost.setText(String.format("📊 Средняя цена: %.2f ₽", avg)); }); btnShowLessThanAverage.setOnClickListener(v -> { viewModel.getProductsLessThanAverage().observe(getViewLifecycleOwner(), products -> { adapter.setProducts(products); tvCountLessThanAvg.setText("📊 Товаров дешевле средней цены: " + products.size()); }); }); return view; } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@+id/nav_host_fragment" android:layout_width="match_parent" android:layout_height="0dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toTopOf="@+id/bottomNavigation" android:layout_marginBottom="0dp"/> <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/bottomNavigation" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:menu="@menu/bottom_nav_menu"/> </androidx.constraintlayout.widget.ConstraintLayout>
dialog_product.xml
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <com.google.android.material.textfield.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Наименование"> <EditText android:id="@+id/etName" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="text"/> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:hint="Стоимость"> <EditText android:id="@+id/etCost" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberDecimal"/> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:hint="Дата выпуска (ГГГГ-ММ-ДД)"> <EditText android:id="@+id/etReleaseDate" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="date" android:text="2024-01-01"/> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:hint="Производитель"> <EditText android:id="@+id/etManufacturer" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="text"/> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:hint="Единица измерения (шт/мл/г)"> <EditText android:id="@+id/etUnit" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="text"/> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:hint="Цена поставщика"> <EditText android:id="@+id/etSupplierPrice" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberDecimal"/> </com.google.android.material.textfield.TextInputLayout> </LinearLayout> </ScrollView>
fragment_filter.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="8dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="🔍 Фильтр по цене" android:textSize="22sp" android:textStyle="bold"/> <com.google.android.material.textfield.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:hint="Минимальная цена"> <EditText android:id="@+id/etMinCost" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="numberDecimal"/> </com.google.android.material.textfield.TextInputLayout> <Button android:id="@+id/btnFilter" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Показать товары с ценой выше" android:layout_marginTop="8dp"/> <TextView android:id="@+id/tvCountFilter" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="📊 Введите значение и нажмите кнопку" android:textSize="14sp" android:textColor="#666666" android:layout_marginTop="8dp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="📦 Результат:" android:textSize="16sp" android:textStyle="bold" android:layout_marginTop="12dp"/> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerViewFilter" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="4dp"/> </LinearLayout>
fragment_group.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="8dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="👥 Группировка данных" android:textSize="22sp" android:textStyle="bold"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginTop="8dp"> <Button android:id="@+id/btnGroupManufacturer" android:layout_width="0dp" android:layout_height="match_parent" android:layout_marginEnd="4dp" android:layout_weight="1" android:text="По производителю" /> <Button android:id="@+id/btnGroupUnit" android:layout_width="0dp" android:layout_height="match_parent" android:layout_marginStart="4dp" android:layout_weight="1" android:text="По единице изм." /> </LinearLayout> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="8dp"> <TextView android:id="@+id/tvGroupResult" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Нажмите на кнопку для группировки" android:textSize="16sp"/> </ScrollView> </LinearLayout>
fragment_list.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="8dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="📋 Список товаров" android:textSize="22sp" android:textStyle="bold"/> <Button android:id="@+id/btnAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="➕ Добавить" android:backgroundTint="#4CAF50"/> </LinearLayout> <TextView android:id="@+id/tvCount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="📊 Всего товаров: 0" android:textSize="14sp" android:textColor="#666666" android:layout_marginTop="4dp"/> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="8dp"/> </LinearLayout>
