Android SearchView 返回键无效解决方案

本文介绍了解决Android中SearchView控件的一个常见问题:当设置了iconifiedByDefault为false时,控件获取焦点后按返回键无法退出的情况。通过简单的代码修改即可实现正常返回。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android中SearchView控件在设置iconifiedByDefault=”false”时会出现一个问题:打开页面控件获取到焦点后,按返回键无法返回。

解决方案

mSearchView.setFocusableInTouchMode(true);

package com.example.kucun2.ui.jinhuo; import android.app.AlertDialog; import android.app.DatePickerDialog; import android.app.ProgressDialog; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.Button; import android.widget.EditText; import android.widget.RadioGroup; import android.widget.SearchView; import android.widget.Spinner; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import com.example.kucun2.R; import com.example.kucun2.entity.*; import com.example.kucun2.DataPreserver.Data; import com.example.kucun2.entity.data.ReflectionJsonUtils; import com.example.kucun2.entity. data.SynchronizableEntity; import com.example.kucun2.function.Adapter; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.stream.Collectors; public class AddInventoryFragment extends Fragment { // UI组件声明 private Spinner spinnerDingdan, spinnerChanpin, spinnerZujian, spinnerBancai; private EditText etShuliang; private RadioGroup rgType; private Button btnNewDingdan, btnAddChanpin, btnAddZujian; private ProgressDialog progressDialog; // 添加进度条 // 当前选中项 private Dingdan selectedDingdan; private Chanpin selectedChanpin; private Zujian selectedZujian; private Bancai selectedBancai; private View rootView; // 日期格式化工具 private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); private static final String TAG = "AddInventoryFragment"; @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.fragment_add_inventory, container, false); initViews(rootView); setupEventListeners(); // 初始化下拉框数据(使用已加载的数据) setupSpinnersWithExistingData(); return rootView; } /** 初始化UI组件 */ private void initViews(View view) { spinnerDingdan = view.findViewById(R.id.spinner_dingdan); spinnerChanpin = view.findViewById(R.id.spinner_chanpin); spinnerZujian = view.findViewById(R.id.spinner_zujian); spinnerBancai = view.findViewById(R.id.spinner_bancai); etShuliang = view.findViewById(R.id.et_shuliang); rgType = view.findViewById(R.id.rg_type); btnNewDingdan = view.findViewById(R.id.btn_new_dingdan); btnAddChanpin = view.findViewById(R.id.btn_add_chanpin); btnAddZujian = view.findViewById(R.id.btn_add_zujian); } /** * 使用已加载的数据初始化下拉框 */ private void setupSpinnersWithExistingData() { // 1. 设置订单下拉框 setupDingdanSpinner(); // 2. 如果存在选中的订单,设置产品下拉框 if (selectedDingdan != null) { setupChanpinSpinner(selectedDingdan); } // 3. 如果存在选中的产品,设置组件下拉框 if (selectedChanpin != null) { setupZujianSpinner(selectedChanpin); } // 4. 如果存在选中的产品和组件,设置板材下拉框 if (selectedChanpin != null && selectedZujian != null) { setupBancaiSpinner(selectedChanpin, selectedZujian); } } // 修改 setupDingdanSpinner 方法,使用现有数据 private void setupDingdanSpinner() { // 过滤掉预置对象(ID=-1) List<Dingdan> validDingdans = Data.dingdans().stream() .filter(d -> d.getId() != null) .collect(Collectors.toList()); Adapter.setupDingdanSpinner(spinnerDingdan, validDingdans, getContext()); // 设置默认选中项(如果有) if (!validDingdans.isEmpty()) { spinnerDingdan.setSelection(0); selectedDingdan = validDingdans.get(0); } } /** 设置事件监听器 */ private void setupEventListeners() { // 新建订单按钮 btnNewDingdan.setOnClickListener(v -> showNewDingdanDialog()); // 添加产品按钮 btnAddChanpin.setOnClickListener(v -> showAddChanpinDialog()); // 添加组件按钮 btnAddZujian.setOnClickListener(v -> { if (selectedChanpin == null) { Toast.makeText(getContext(), "请先选择产品", Toast.LENGTH_SHORT).show(); return; } showCreateZujianDialog(); }); // 提交按钮 rootView.findViewById(R.id.btn_submit).setOnClickListener(v -> addInventoryRecord()); // 订单下拉框监听 spinnerDingdan.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { selectedDingdan = (Dingdan) parent.getItemAtPosition(position); setupChanpinSpinner(selectedDingdan); } @Override public void onNothingSelected(AdapterView<?> parent) {} }); } /** 设置产品下拉框 */ private void setupChanpinSpinner(Dingdan dingdan) { List<Chanpin> chanpins = new ArrayList<>(); if (dingdan != null && dingdan.getDingdanChanpin() != null) { for (Dingdan_Chanpin dc : dingdan.getDingdanChanpin()) { if (dc != null && dc.getChanpin() != null) { chanpins.add(dc.getChanpin()); } } } Adapter.setupChanpinSpinner(spinnerChanpin, chanpins, getContext()); spinnerChanpin.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { selectedChanpin = (Chanpin) parent.getItemAtPosition(position); if (selectedChanpin != null) { setupZujianSpinner(selectedChanpin); } } @Override public void onNothingSelected(AdapterView<?> parent) {} }); } /** 设置组件下拉框 */ private void setupZujianSpinner(Chanpin chanpin) { List<Zujian> zujians = new ArrayList<>(); for (Chanpin_Zujian cz : chanpin.getChanpinZujian()) { zujians.add(cz.getZujian()); } Adapter.setupZujianSpinner(spinnerZujian, zujians, getContext()); spinnerZujian.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { selectedZujian = (Zujian) parent.getItemAtPosition(position); setupBancaiSpinner(selectedChanpin, selectedZujian); } @Override public void onNothingSelected(AdapterView<?> parent) {} }); } /** 设置板材下拉框 */ private void setupBancaiSpinner(Chanpin chanpin, Zujian zujian) { List<Bancai> bancais = new ArrayList<>(); for (Chanpin_Zujian cz : chanpin.getChanpinZujian()) { if (cz.getZujian().getId().equals(zujian.getId())) { bancais.add(cz.getBancai()); } } Adapter.setupBancaiSpinners(spinnerBancai, bancais, getContext()); spinnerBancai.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { selectedBancai = (Bancai) parent.getItemAtPosition(position); Log.d(TAG, "Selected bancai: " + (selectedBancai != null ? selectedBancai.TableText() : "null")); } @Override public void onNothingSelected(AdapterView<?> parent) { selectedBancai = null; Log.d(TAG, "Selected bancai: " + (selectedBancai != null ? selectedBancai.TableText() : "null")); } }); // 设置默认选中项 if (!bancais.isEmpty()) { spinnerBancai.setSelection(0); selectedBancai = bancais.get(0); // 确保默认选中第一项 }else { selectedBancai = null; // 明确设置为null Toast.makeText(getContext(), "该组件未关联板材,请先添加关联", Toast.LENGTH_SHORT).show(); } } /** 添加库存记录 */ private void addInventoryRecord() { // 验证必填项 if (selectedDingdan == null || selectedChanpin == null || selectedZujian == null || selectedBancai == null) { Log.d("addInventoryRecord","selectedDingdan:"+selectedDingdan); Log.d("addInventoryRecord","selectedChanpin:"+selectedChanpin); Log.d("addInventoryRecord","selectedZujian:"+selectedZujian); Log.d("addInventoryRecord","selectedBancai:"+selectedBancai); Toast.makeText(getContext(), "请选择订单、产品、组件和板材", Toast.LENGTH_SHORT).show(); return; } String shuliangStr = etShuliang.getText().toString().trim(); if (shuliangStr.isEmpty()) { Toast.makeText(getContext(), "请输入数量", Toast.LENGTH_SHORT).show(); return; } // 新增板材空值检查 if (selectedBancai == null) { Toast.makeText(getContext(), “请为组件选择关联的板材”, Toast.LENGTH_SHORT).show(); return; } try { int shuliang = Integer.parseInt(shuliangStr); boolean isJinhuo = rgType.getCheckedRadioButtonId() == R.id.rb_jinhuo; User currentUser=null; if (Data.getUser()==null) { currentUser = new User(1, “当前用户”, “user”, “password”, 1); }else { currentUser=Data.getUser(); } createRecord(selectedDingdan, selectedChanpin, selectedZujian, selectedBancai, shuliang, isJinhuo, currentUser); Toast.makeText(getContext(), "记录添加成功", Toast.LENGTH_SHORT).show(); etShuliang.setText(""); } catch (NumberFormatException e) { Toast.makeText(getContext(), "请输入有效的数量", Toast.LENGTH_SHORT).show(); } } /** 显示添加产品对话框 */ private void showAddChanpinDialog() { if (selectedDingdan == null) { Toast.makeText(getContext(), "请先选择订单", Toast.LENGTH_SHORT).show(); return; } AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("添加产品到订单"); View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_add_chanpin, null); Spinner spinnerChanpinSelection = dialogView.findViewById(R.id.spinner_chanpin_selection); EditText etQuantity = dialogView.findViewById(R.id.et_chanpin_quantity); Button btnNewChanpin = dialogView.findViewById(R.id.btn_new_chanpin); // 设置产品下拉框 if ( Data.chanpins().isEmpty()) { Toast.makeText(getContext(), "没有可用的产品,请先创建产品", Toast.LENGTH_SHORT).show(); return; } Adapter.setupChanpinSpinner(spinnerChanpinSelection, Data.chanpins(), getContext()); // 设置新建产品按钮点击事件 btnNewChanpin.setOnClickListener(v -> { showNewChanpinDialog(spinnerChanpinSelection); }); builder.setView(dialogView); builder.setPositiveButton("添加", (dialog, which) -> { Chanpin selected = (Chanpin) spinnerChanpinSelection.getSelectedItem(); String quantityStr = etQuantity.getText().toString().trim(); if (selected == null) { Toast.makeText(getContext(), "请选择产品", Toast.LENGTH_SHORT).show(); return; } if (quantityStr.isEmpty()) { Toast.makeText(getContext(), "请输入数量", Toast.LENGTH_SHORT).show(); return; } try { int quantity = Integer.parseInt(quantityStr); addChanpinToDingdan(selected, quantity); } catch (NumberFormatException e) { Toast.makeText(getContext(), "请输入有效的数量", Toast.LENGTH_SHORT).show(); } }); builder.setNegativeButton("取消", null); builder.show(); } /** 显示新建产品对话框 */ private void showNewChanpinDialog(Spinner spinnerToRefresh) { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("新建产品"); View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_new_chanpin, null); EditText etName = dialogView.findViewById(R.id.et_chanpin_name); builder.setView(dialogView); builder.setPositiveButton("创建", (dialog, which) -> { String bianhao = etName.getText().toString().trim(); if (bianhao.isEmpty()) { Toast.makeText(getContext(), "请输入产品名称", Toast.LENGTH_SHORT).show(); return; } // 检查产品编号是否重复 for (Chanpin c : Data.chanpins()) { if (c.getBianhao().equals(bianhao)) { Toast.makeText(getContext(), "产品编号已存在", Toast.LENGTH_SHORT).show(); return; } } createAndSaveChanpin(bianhao, spinnerToRefresh); }); builder.setNegativeButton("取消", null); builder.show(); } /** 创建并保存新产品 */ private void createAndSaveChanpin(String name, Spinner spinnerToRefresh) { Chanpin newChanpin = new Chanpin(); newChanpin.setId( Data.chanpins().size() + 10000); newChanpin.setBianhao(name); newChanpin.setChanpinZujian(new ArrayList<>()); // 初始化组件列表 Data.chanpins().add(newChanpin); // 刷新产品下拉框 Adapter.setupChanpinSpinner(spinnerToRefresh, Data.chanpins(), getContext()); // 选中新创建的产品 for (int i = 0; i < spinnerToRefresh.getCount(); i++) { Chanpin item = (Chanpin) spinnerToRefresh.getItemAtPosition(i); if (item.getId().equals(newChanpin.getId())) { spinnerToRefresh.setSelection(i); break; } } Toast.makeText(getContext(), "产品创建成功", Toast.LENGTH_SHORT).show(); } /** 显示新建订单对话框 */ private void showNewDingdanDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("新建订单"); View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_new_dingdan, null); // 初始化视图 EditText etOrderNumber = dialogView.findViewById(R.id.et_order_number); EditText etOrderDate = dialogView.findViewById(R.id.et_order_date); EditText etdeliveryDate = dialogView.findViewById(R.id.et_delivery_date); Button btnPickOrderDate = dialogView.findViewById(R.id.btn_pick_order_date); Button btnPickdeliveryDate = dialogView.findViewById(R.id.btn_pick_delivery_date); // 设置默认日期 etOrderDate.setText(dateFormat.format(new Date())); etdeliveryDate.setText(dateFormat.format(new Date())); // 日期选择器 btnPickOrderDate.setOnClickListener(v -> showDatePicker(etOrderDate)); btnPickdeliveryDate.setOnClickListener(v -> showDatePicker(etdeliveryDate)); builder.setView(dialogView); builder.setPositiveButton("创建", (dialog, which) -> { String orderNumber = etOrderNumber.getText().toString().trim(); if (orderNumber.isEmpty()) { Toast.makeText(getContext(), "请输入订单号", Toast.LENGTH_SHORT).show(); return; } // 检查订单号是否重复 for (Dingdan d : Data.dingdans()) { if (d.getNumber().equals(orderNumber)) { Toast.makeText(getContext(), "订单号已存在", Toast.LENGTH_SHORT).show(); return; } } try { Date orderDate = dateFormat.parse(etOrderDate.getText().toString()); Date deliveryDate = dateFormat.parse(etdeliveryDate.getText().toString()); createAndSaveDingdan(orderNumber, orderDate, deliveryDate); } catch (ParseException e) { Toast.makeText(getContext(), "日期格式错误", Toast.LENGTH_SHORT).show(); } }); builder.setNegativeButton("取消", null); builder.show(); } /** 显示日期选择器 */ private void showDatePicker(EditText targetField) { Calendar cal = Calendar.getInstance(); new DatePickerDialog(requireContext(), (view, year, month, dayOfMonth) -> { Calendar selected = Calendar.getInstance(); selected.set(year, month, dayOfMonth); targetField.setText(dateFormat.format(selected.getTime())); }, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH) ).show(); } /*** * 显示添加组件对话框 */ private void showCreateZujianDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("添加新组件"); View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_create_zujian_bancai, null); // 初始化视图 Spinner etZujianName = dialogView.findViewById(R.id.et_zujian_name); Spinner spinnerbancai = dialogView.findViewById(R.id.spinner_bancai); SearchView searchBancai = dialogView.findViewById(R.id.search_bancai); EditText numberOne_howmany=dialogView.findViewById(R.id.number_one_howmany); Button btzujian =dialogView.findViewById(R.id.btn_add_zujian); Button btbanci=dialogView.findViewById(R.id.btn_add_bancai); btbanci.setOnClickListener(v -> showNewBancaiDialog(spinnerbancai)); // 新建组件按钮点击事件 - 新添加的功能 btzujian.setOnClickListener(v -> showNewZujianDialog(etZujianName)); // 设置适配器 Adapter.setupZujianSpinner(etZujianName, Data.zujians(), getContext()); Adapter.setupBancaiSpinners(spinnerbancai, Data.bancais(), getContext()); // 设置搜索功能 searchBancai.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { return false; } @Override public boolean onQueryTextChange(String newText) { List<Bancai> filtered = new ArrayList<>(); for (Bancai b : Data.bancais()) { if (b.TableText().toLowerCase().contains(newText.toLowerCase())) { filtered.add(b); } } Adapter.setupBancaiSpinners(spinnerbancai, filtered, getContext()); return true; } }); builder.setView(dialogView); builder.setPositiveButton("创建", (dialog, which) -> { Zujian zujian = (Zujian) etZujianName.getSelectedItem(); Bancai bancai = (Bancai) spinnerbancai.getSelectedItem(); String One_howmany= numberOne_howmany.getText().toString(); if (zujian == null || bancai == null) { Toast.makeText(getContext(), "请选择组件和板材", Toast.LENGTH_SHORT).show(); return; } if (One_howmany==null){ Toast.makeText(getContext(), "请选择板材生产多少组件", Toast.LENGTH_SHORT).show(); return; } // 检查是否已存在相同的组合 boolean isDuplicate = false; for (Chanpin_Zujian existing : selectedChanpin.getChanpinZujian()) { if (existing.getZujian().equals(zujian) && existing.getBancai().equals(bancai)) { isDuplicate = true; break; } } if (isDuplicate) { Toast.makeText(getContext(), "该产品和组件组合已存在,不能重复添加", Toast.LENGTH_SHORT).show(); return; } // 创建关联对象 Chanpin_Zujian cz = new Chanpin_Zujian(); cz.setZujian(zujian); cz.setBancai(bancai); cz.setChanpin(selectedChanpin); cz.setOne_howmany(Double.valueOf(One_howmany));//double类型 selectedChanpin.getChanpinZujian().add(cz); Dingdan_chanpin_zujian dz=new Dingdan_chanpin_zujian(); dz.setBancai(selectedBancai); dz.setZujian(cz); //存入 Data.Dingdan_chanpin_zujians().add(dz); Data.chanpin_zujians().add(cz); // 刷新UI setupZujianSpinner(selectedChanpin); spinnerZujian.setSelection(selectedChanpin.getChanpinZujian().size() - 1); Toast.makeText(getContext(), "组件添加成功", Toast.LENGTH_SHORT).show(); }); builder.setNegativeButton("取消", null); builder.show(); } /** * 显示创建组件 * @param spinnerToRefresh */ private void showNewZujianDialog(Spinner spinnerToRefresh) { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("新建组件"); View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_new_zujian, null); EditText etName = dialogView.findViewById(R.id.et_zujian_name); builder.setView(dialogView); builder.setPositiveButton("创建", (dialog, which) -> { String name = etName.getText().toString().trim(); if (name.isEmpty()) { Toast.makeText(getContext(), "请输入组件名称", Toast.LENGTH_SHORT).show(); return; } // 检查组件名称是否重复 for (Zujian z : Data.zujians()) { if (z.getName().equals(name)) { Toast.makeText(getContext(), "组件名称已存在", Toast.LENGTH_SHORT).show(); return; } } createAndSaveZujian(name, spinnerToRefresh); }); builder.setNegativeButton("取消", null); builder.show(); } /*** * 显示新建板材对话框 * @param spinnerToRefresh */ private void showNewBancaiDialog(Spinner spinnerToRefresh) { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("新建板材"); View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_add_bancai, null); Spinner spinnerCaizhi = dialogView.findViewById(R.id.spinner_caizhi); Spinner spinnerMupi1 = dialogView.findViewById(R.id.spinner_mupi1); Spinner spinnerMupi2 = dialogView.findViewById(R.id.spinner_mupi2); Button btnNewCaizhi = dialogView.findViewById(R.id.btn_new_caizhi); Button btnNewMupi = dialogView.findViewById(R.id.btn_new_mupi); EditText etHoudu = dialogView.findViewById(R.id.et_houdu); // 设置材质下拉框 Adapter.setupCaizhiSpinner(spinnerCaizhi, Data.caizhis(), getContext()); // 设置木皮下拉框 Adapter.setupMupiSpinner(spinnerMupi1, Data.mupis(), getContext()); Adapter.setupMupiSpinner(spinnerMupi2, Data.mupis(), getContext()); // 新建材质按钮点击事件 btnNewCaizhi.setOnClickListener(v -> { showNewCaizhiDialog(spinnerCaizhi); }); // 新建木皮按钮点击事件 btnNewMupi.setOnClickListener(v -> { showNewMupiDialog(spinnerMupi1, spinnerMupi2); }); builder.setView(dialogView); builder.setPositiveButton("创建", (dialog, which) -> { Caizhi selectedCaizhi = (Caizhi) spinnerCaizhi.getSelectedItem(); Mupi selectedMupi1 = (Mupi) spinnerMupi1.getSelectedItem(); Mupi selectedMupi2 = (Mupi) spinnerMupi2.getSelectedItem(); String houduStr = etHoudu.getText().toString().trim(); if (selectedCaizhi == null) { Toast.makeText(getContext(), "请选择材质", Toast.LENGTH_SHORT).show(); return; } if (houduStr.isEmpty()) { Toast.makeText(getContext(), "请输入厚度", Toast.LENGTH_SHORT).show(); return; } try { double houdu = Double.parseDouble(houduStr); createAndSaveBancai(selectedCaizhi, selectedMupi1, selectedMupi2, houdu, spinnerToRefresh); } catch (NumberFormatException e) { Toast.makeText(getContext(), "请输入有效的厚度值", Toast.LENGTH_SHORT).show(); } }); builder.setNegativeButton("取消", null); builder.show(); } /** 显示新建材质对话框 */ private void showNewCaizhiDialog(Spinner spinnerToRefresh) { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("新建材质"); View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_new_caizhi, null); EditText etName = dialogView.findViewById(R.id.et_caizhi_name); builder.setView(dialogView); builder.setPositiveButton("创建", (dialog, which) -> { String name = etName.getText().toString().trim(); if (name.isEmpty()) { Toast.makeText(getContext(), "请输入材质名称", Toast.LENGTH_SHORT).show(); return; } // 检查材质名称是否重复 for (Caizhi c : Data.caizhis()) { if (c.getName().equals(name)) { Toast.makeText(getContext(), "材质名称已存在", Toast.LENGTH_SHORT).show(); return; } } createAndSaveCaizhi(name, spinnerToRefresh); }); builder.setNegativeButton("取消", null); builder.show(); } /** * 创建新组件保存 * @param name * @param spinnerToRefresh */ private void createAndSaveZujian(String name, Spinner spinnerToRefresh) { Zujian newZujian = new Zujian(); newZujian.setId(Data.zujians().size() + 10000); newZujian.setName(name); Data.zujians().add(newZujian); // 刷新组件下拉框 Adapter.setupZujianSpinner(spinnerToRefresh, Data.zujians(), getContext()); // 选中新创建的组件 for (int i = 0; i < spinnerToRefresh.getCount(); i++) { Zujian item = (Zujian) spinnerToRefresh.getItemAtPosition(i); if (item.getId().equals(newZujian.getId())) { spinnerToRefresh.setSelection(i); break; } } Toast.makeText(getContext(), "组件创建成功", Toast.LENGTH_SHORT).show(); } /** * 新建木皮set * @param spinnerMupi1 * @param spinnerMupi2 */ // 在 AddInventoryFragment.java 中添加木皮创建功能 private void showNewMupiDialog(Spinner spinnerMupi1, Spinner spinnerMupi2) { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("新建木皮"); View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_new_mupi, null); EditText etMupiName = dialogView.findViewById(R.id.et_mupi_name); RadioGroup rgFinish = dialogView.findViewById(R.id.rg_finish); builder.setView(dialogView); builder.setPositiveButton("创建", (dialog, which) -> { String name = etMupiName.getText().toString().trim(); boolean isPainted = rgFinish.getCheckedRadioButtonId() == R.id.rb_painted; if (name.isEmpty()) { Toast.makeText(getContext(), "请输入木皮名称", Toast.LENGTH_SHORT).show(); return; } // 检查木皮名称是否重复 for (Mupi m : Data.mupis()) { if (m.getName().equals(name)&&m.getYou().equals(isPainted)) { Toast.makeText(getContext(), "木皮已存在", Toast.LENGTH_SHORT).show(); return; } } createAndSaveMupi(name, isPainted, spinnerMupi1, spinnerMupi2); }); builder.setNegativeButton("取消", null); builder.show(); } /** 创建并保存订单 */ private void createAndSaveDingdan(String orderNumber, Date orderDate, Date deliveryDate) { Dingdan newDingdan = new Dingdan(); newDingdan.setId( Data.dingdans().size() + 10000); newDingdan.setNumber(orderNumber); newDingdan.setXiadan(orderDate); newDingdan.setJiaohuo(deliveryDate); newDingdan.setDingdanChanpin(new ArrayList<>()); Log.d(TAG, "createAndSaveDingdan: " +ReflectionJsonUtils.toJson(newDingdan)); Data.dingdans().add(newDingdan); // 刷新UI setupDingdanSpinner(); spinnerDingdan.setSelection( Data.dingdans().size() - 1); Toast.makeText(getContext(), "新建订单成功", Toast.LENGTH_SHORT).show(); } /** 添加产品到订单(带数量) */ private void addChanpinToDingdan(Chanpin chanpin, int quantity) { // 检查是否已添加 for (Dingdan_Chanpin dc : selectedDingdan.getDingdanChanpin()) { if (dc.getChanpin().getId().equals(chanpin.getId())) { Toast.makeText(getContext(), "该产品已添加到订单", Toast.LENGTH_SHORT).show(); return; } } // 创建关联对象 Dingdan_Chanpin dc = new Dingdan_Chanpin(); dc.setChanpin(chanpin); dc.setDingdan(selectedDingdan); dc.setShuliang(quantity); // 设置产品数量 selectedDingdan.getDingdanChanpin().add(dc); Data.dingdan_chanpins().add(dc); // 刷新UI setupChanpinSpinner(selectedDingdan); spinnerChanpin.setSelection(selectedDingdan.getDingdanChanpin().size() - 1); Toast.makeText(getContext(), "产品添加成功", Toast.LENGTH_SHORT).show(); } /** 创建并保存新板材 */ private void createAndSaveBancai(Caizhi caizhi, Mupi mupi1, Mupi mupi2, double houdu, Spinner spinnerToRefresh) { Bancai newBancai = new Bancai(); newBancai.setId( Data.bancais().size() + 10000); newBancai.setCaizhi(caizhi); newBancai.setMupi1(mupi1); newBancai.setMupi2(mupi2); newBancai.setHoudu(houdu); Data.bancais().add(newBancai); Data.kucuns().add(new Kucun(Data.kucuns().size() + 10000,0,newBancai)); // 刷新板材下拉框 Adapter.setupBancaiSpinners(spinnerToRefresh, Data.bancais(), getContext()); // 选中新创建的板材 for (int i = 0; i < spinnerToRefresh.getCount(); i++) { Bancai item = (Bancai) spinnerToRefresh.getItemAtPosition(i); if (item.getId().equals(newBancai.getId())) { spinnerToRefresh.setSelection(i); break; } } Toast.makeText(getContext(), "板材创建成功", Toast.LENGTH_SHORT).show(); } /** 创建并保存新材质 */ private void createAndSaveCaizhi(String name, Spinner spinnerToRefresh) { Caizhi newCaizhi = new Caizhi(); newCaizhi.setId( Data.caizhis().size() + 10000); newCaizhi.setName(name); Data.caizhis().add(newCaizhi); // 刷新材质下拉框 Adapter.setupCaizhiSpinner(spinnerToRefresh, Data.caizhis(), getContext()); // 选中新创建的材质 for (int i = 0; i < spinnerToRefresh.getCount(); i++) { Caizhi item = (Caizhi) spinnerToRefresh.getItemAtPosition(i); if (item.getId().equals(newCaizhi.getId())) { spinnerToRefresh.setSelection(i); break; } } Toast.makeText(getContext(), "材质创建成功", Toast.LENGTH_SHORT).show(); } /** 创建并保存新木皮 */ private void createAndSaveMupi(String name, boolean isPainted, Spinner spinner1, Spinner spinner2) { Mupi newMupi = new Mupi(); newMupi.setId( Data.mupis().size() + 10000); newMupi.setName(name); newMupi.setYou(isPainted); Data.mupis().add(newMupi); // 刷新木皮下拉框 Adapter.setupMupiSpinner(spinner1, Data.mupis(), getContext()); Adapter.setupMupiSpinner(spinner2, Data.mupis(), getContext()); // 选中新创建的木皮 for (int i = 0; i < spinner1.getCount(); i++) { Mupi item = (Mupi) spinner1.getItemAtPosition(i); if (item.getId().equals(newMupi.getId())) { spinner1.setSelection(i); spinner2.setSelection(i); break; } } Toast.makeText(getContext(), "木皮创建成功", Toast.LENGTH_SHORT).show(); } /** 创建库存记录 */ private void createRecord(Dingdan dingdan, Chanpin chanpin, Zujian zujian, Bancai bancai, int shuliang, boolean isJinhuo, User user) { Dingdan_chanpin_zujian din=null; for(Dingdan_chanpin_zujian dz:Data.Dingdan_chanpin_zujians()){ if (dz==null||dz.getDingdian()==null){ continue; } if(dz.getDingdian().getId().equals(dingdan.getId())){ dz.setShuliang(shuliang+dz.getShuliang()); din=dz; } } Log.d(TAG, "onItemSelected: "+ReflectionJsonUtils.toJson(selectedZujian)); Log.d(TAG, "onItemSelected: "+ReflectionJsonUtils.toJson(zujian)); Log.d(TAG, "onItemSelected: "+ReflectionJsonUtils.toJson(Data.chanpin_zujians())); if (din==null){ din=new Dingdan_chanpin_zujian(); din.setId(Data.Dingdan_chanpin_zujians().size()+10000); din.setDingdian(dingdan); din.setShuliang(shuliang); din.setZujian(Data.chanpin_zujians().stream() .filter(v-> Objects.equals(v.getZujian().getId(), zujian.getId())) .findFirst() .orElse( new Chanpin_Zujian(Data.dingdan_chanpins().size()+10000,chanpin,zujian,bancai,(double)shuliang) )); } Data.Dingdan_chanpin_zujians().add(din); if (isJinhuo) { Jinhuo jinhuo = new Jinhuo(); jinhuo.setId( Data.jinhuos().size() + 10000); jinhuo.setDingdan(dingdan); jinhuo.setChanpin(chanpin); jinhuo.setZujian(zujian); jinhuo.setBancai(bancai); jinhuo.setShuliang(shuliang); jinhuo.setDate(new Date()); jinhuo.setUser(user); Data.jinhuos().add(jinhuo); } else { shuliang = -shuliang; } updateKucun(bancai, shuliang); } /** 更新库存 */ private void updateKucun(Bancai bancai, int changeAmount) { Log.d(TAG,(bancai==null)?"null":bancai.getId()+""); for (Kucun k : Data.kucuns()) { Log.d(TAG, ReflectionJsonUtils.toJson(k)); if (k.getBancai()!=null&&k.getBancai().getId().equals(bancai.getId())) { k.setShuliang(k.getShuliang() + changeAmount); return; } } // 创建新库存记录 Kucun newKucun = new Kucun(); newKucun.setId( Data.kucuns().size() + 10000); newKucun.setBancai(bancai); newKucun.setShuliang(Math.max(changeAmount, 0)); Data.kucuns().add(newKucun); } public void addOrderComponent(Chanpin_Zujian cz, Dingdan_chanpin_zujian dz) { // 第一步:添加产品组件 Data.chanpin_zujians().add(cz); // 第二步:等待产品组件同步完成 cz.sync(new SynchronizableEntity.SyncCallback() { @Override public void onSyncSuccess(SynchronizableEntity entity) { // 第三步:设置关联ID dz.setZujian(cz); // 第四步:添加订单组件关联 Data.Dingdan_chanpin_zujians().add(dz); // 第五步:同步订单组件关联 dz.sync(new SynchronizableEntity.SyncCallback() { @Override public void onSyncSuccess(SynchronizableEntity entity) { Log.d("SyncChain", "All entities synced successfully!"); } @Override public void onSyncFailure(String error) { Log.e("SyncChain", "Failed to sync dz: " + error); } }); } @Override public void onSyncFailure(String error) { Log.e("SyncChain", "Failed to sync cz: " + error); } }); } }package com.example.kucun2.entity.data; import android.os.Handler; import android.os.Looper; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.*; public class SynchronizedList implements List { private final List list = new ArrayList<>(); private final Class entityType; private final EntityChangeListener entityChangeListener = new EntityChangeListener<>(); private static final String TAG = “SynchronizedList”; // 添加TAG public SynchronizedList(Class entityType) { this.entityType = entityType; } //================ 监听器管理 ================// private static class EntityChangeListener<T extends SynchronizableEntity> implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { ((T) evt.getSource()).sync(null); } } private void registerListener(T element) { if (element != null) { element.addPropertyChangeListener(entityChangeListener); } } private void unregisterListener(Object element) { if (element instanceof SynchronizableEntity) { ((SynchronizableEntity) element).removePropertyChangeListener(entityChangeListener); } } //================ 核心集合操作 ================// @Override public boolean add(T element) { if (element != null && !list.contains(element)) { registerListener(element); boolean added = list.add(element); Log.d(TAG, "添加实体: " + element + ", 状态: " + element.getState()); // 修改:所有需要同步的状态都触发自动同步 if (added && element.requiresSync()) { Log.d(TAG, "触发自动同步: " + element); triggerAutoSync(element); } return added; } return false; } // 修改后的自动同步方法 private void triggerAutoSync(T element) { Log.d(TAG, "安排自动同步: " + element); // 确保在主线程执行 if (Looper.myLooper() == Looper.getMainLooper()) { performSync(element); } else { new Handler(Looper.getMainLooper()).post(() -> performSync(element)); } } private void performSync(T element) { Log.d(TAG, "执行同步: " + element + ", 是否在列表中: " + list.contains(element)); // 即使实体不在列表中仍尝试同步 element.syncWithDependencies(new SynchronizableEntity.SyncCallback() { @Override public void onSyncSuccess(SynchronizableEntity entity) { Log.i(TAG, "同步成功: " + entity); } @Override public void onSyncFailure(String error) { Log.e(TAG, "同步失败: " + error + ", 实体: " + element); } }); } @Override public boolean remove(Object o) { if (list.remove(o)) { unregisterListener(o); return true; } return false; } @Override public void clear() { for (T element : list) { unregisterListener(element); } list.clear(); } //================ 批量操作 ================// @Override public boolean addAll(@NonNull Collection<? extends T> c) { boolean modified = false; for (T element : c) { if (add(element)) { modified = true; } } return modified; } @Override public boolean addAll(int index, @NonNull Collection<? extends T> c) { if (index < 0 || index > size()) throw new IndexOutOfBoundsException(); int i = index; for (T element : c) { if (element != null && !list.contains(element)) { add(i++, element); } } return i > index; } @Override public boolean removeAll(@NonNull Collection<?> c) { boolean modified = false; for (Object o : c) { while (remove(o)) { modified = true; } } return modified; } @Override public boolean retainAll(@NonNull Collection<?> c) { boolean modified = false; Iterator<T> it = iterator(); while (it.hasNext()) { T element = it.next(); if (!c.contains(element)) { it.remove(); modified = true; } } return modified; } //================ 索引操作 ================// @Override public T get(int index) { return list.get(index); } @Override public T set(int index, T element) { if (element == null) throw new NullPointerException(); if (list.contains(element)) throw new IllegalArgumentException("Duplicate element"); T old = list.get(index); unregisterListener(old); registerListener(element); return list.set(index, element); } @Override public void add(int index, T element) { if (element == null) throw new NullPointerException(); if (list.contains(element)) throw new IllegalArgumentException("Duplicate element"); registerListener(element); list.add(index, element); } @Override public T remove(int index) { T removed = list.remove(index); if (removed != null) { unregisterListener(removed); } return removed; } //================ 查询操作 ================// @Override public int size() { return list.size(); } @Override public boolean isEmpty() { return list.isEmpty(); } @Override public boolean contains(Object o) { return list.contains(o); } @Override public boolean containsAll(@NonNull Collection<?> c) { return list.containsAll(c); } @Override public int indexOf(@Nullable Object o) { return list.indexOf(o); } @Override public int lastIndexOf(@Nullable Object o) { return list.lastIndexOf(o); } //================ 迭代器实现 ================// @NonNull @Override public Iterator<T> iterator() { return new Iterator<>() { private final Iterator<T> iterator = list.iterator(); private T current; @Override public boolean hasNext() { return iterator.hasNext(); } @Override public T next() { current = iterator.next(); return current; } @Override public void remove() { unregisterListener(current); iterator.remove(); } }; } @NonNull @Override public ListIterator<T> listIterator() { return listIterator(0); } @NonNull @Override public ListIterator<T> listIterator(int index) { return new ListIterator<T>() { private final ListIterator<T> iterator = list.listIterator(index); private T lastReturned; @Override public boolean hasNext() { return iterator.hasNext(); } @Override public T next() { lastReturned = iterator.next(); return lastReturned; } @Override public boolean hasPrevious() { return iterator.hasPrevious(); } @Override public T previous() { lastReturned = iterator.previous(); return lastReturned; } @Override public int nextIndex() { return iterator.nextIndex(); } @Override public int previousIndex() { return iterator.previousIndex(); } @Override public void remove() { unregisterListener(lastReturned); iterator.remove(); lastReturned = null; } @Override public void set(T t) { if (t == null) throw new NullPointerException(); if (list.contains(t)) throw new IllegalArgumentException("Duplicate element"); unregisterListener(lastReturned); registerListener(t); iterator.set(t); lastReturned = t; } @Override public void add(T t) { if (t == null) throw new NullPointerException(); if (list.contains(t)) throw new IllegalArgumentException("Duplicate element"); registerListener(t); iterator.add(t); lastReturned = null; } }; } //================ 数组转换 ================// @NonNull @Override public Object[] toArray() { return list.toArray(); } @NonNull @Override public <T1> T1[] toArray(@NonNull T1[] a) { return list.toArray(a); } //================ 子视图 ================// @NonNull @Override public List<T> subList(int fromIndex, int toIndex) { throw new UnsupportedOperationException("subList not supported"); } } package com.example.kucun2.entity.data; import android.os.Handler; import android.os.Looper; import android.util.Log; import com.example.kucun2.entity.Information; import com.example.kucun2.entity.RefTo; import com.example.kucun2.entity.RefType; import com.example.kucun2.function.MyAppFunction; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; /** 可同步实体基类 实现实体状态管理、属性变更监听、服务端同步等功能 */ public abstract class SynchronizableEntity implements EntityClassGrassrootsid { private static String TAG=“SynchronizableEntity”; // 实体同步状态枚举 public enum SyncState private SyncState state = SyncState.NEW; private static final int MAX_RETRY = 3; private int retryCount = 0; private static final Map<String, Boolean> syncLocks = new ConcurrentHashMap<>(); private static final ThreadLocal<Set> syncStack = ThreadLocal.withInitial(HashSet::new); // 属性变更支持 private transient PropertyChangeSupport changeSupport; // 属性缓存 private final Map<String, Object> propertyCache = new HashMap<>(); private static boolean syncEnabled = true; // 全局同步开关 //================ 基础方法 ================// /** 判断是否为预保存对象 */ public boolean isPreservedObject() { return this.getId() != null && this.getId() == -1; } /** 设置全局同步开关 */ public static void setSyncEnabled(boolean enabled) { syncEnabled = enabled; } /** 获取/设置实体状态 */ public SyncState getState() { return this.state; } public void setState(SyncState state) { this.state = state; } //================ 属性变更监听 ================// /** 添加属性变更监听器 */ public void addPropertyChangeListener(PropertyChangeListener listener) { if (changeSupport == null) { changeSupport = new PropertyChangeSupport(this); } changeSupport.addPropertyChangeListener(listener); } /** 移除属性变更监听器 */ public void removePropertyChangeListener(PropertyChangeListener listener) { if (changeSupport != null) { changeSupport.removePropertyChangeListener(listener); } } // 触发属性变更时自动同步 protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { if (changeSupport != null && changeSupport.hasListeners(propertyName)) { propertyCache.put(propertyName, newValue); changeSupport.firePropertyChange(propertyName, oldValue, newValue); } // 状态为SYNCED时标记为需要同步 if (state == SyncState.SYNCED) { state = SyncState.MODIFIED; } // 启动同步(非新建实体) if (state != SyncState.NEW && state != SyncState.SYNCING) { scheduleSync(); } } //================ 端点URL生成 ================// /** 获取操作端点URL */ public String getEndpoint(String type) { String key = “url_” + type + “_” + this.getClass().getSimpleName().toLowerCase(); return MyAppFunction.getStringResource(“string”, key); } //================ 核心同步方法 ================// /** 执行同步操作 */ public void sync(SyncCallback callback) { if (!syncEnabled) return; // 检查全局开关 try { switch (this.state) { case NEW: createToServer(callback); break; case MODIFIED: updateToServer(callback); break; case DELETED: deleteFromServer(callback); break; } } catch (Exception e) { Log.e("SyncError", "Sync failed for " + getClass().getSimpleName(), e); } } //================ 服务端操作 ================// /** 创建实体到服务端 */ private void createToServer(SyncCallback callback) { String endpoint = MyAppFunction.getStringResource(“string”, “url”) + getEndpoint(“add”); Information request = new Information<>(200, “Create”, this); Log.d(TAG, "createToServer: "+endpoint); ApiClient.post(endpoint, request, new ApiClient.ApiCallback() { @Override public void onSuccess(Information response) { if (response.getData() != null) { setId(response.getData().getId()); // 设置服务器ID } state = SyncState.SYNCED; if (callback != null) callback.onSyncSuccess(SynchronizableEntity.this); } @Override public void onError(int statusCode, String error) { handleSyncError(error, callback); } }); } /** 更新实体到服务端 */ private void updateToServer(SyncCallback callback) { String endpoint = MyAppFunction.getStringResource(“string”, “url”) + getEndpoint(“update”) + “/” + getId(); Information request = new Information<>(200, “Update”, this); ApiClient.put(endpoint, request, new ApiClient.ApiCallback<SynchronizableEntity>() { @Override public void onSuccess(Information<SynchronizableEntity> response) { state = SyncState.SYNCED; if (callback != null) callback.onSyncSuccess(SynchronizableEntity.this); } @Override public void onError(int statusCode, String error) { handleSyncError(error, callback); } }); } /** 从服务端删除实体 */ private void deleteFromServer(SyncCallback callback) { String endpoint = MyAppFunction.getStringResource(“string”, “url”) + getEndpoint(“delete”) + “/” + getId(); ApiClient.delete(endpoint, new ApiClient.ApiCallback<Void>() { @Override public void onSuccess(Information<Void> response) { state = SyncState.SYNCED; if (callback != null) callback.onSyncSuccess(SynchronizableEntity.this); } @Override public void onError(int statusCode, String error) { handleSyncError(error, callback); } }); } // 安排同步任务(防止频繁同步) private void scheduleSync() { String lockKey = this.getClass().getName() + getId(); synchronized (syncLocks) { if (syncLocks.containsKey(lockKey)) return; syncLocks.put(lockKey, true); } new Handler(Looper.getMainLooper()).postDelayed(() -> { syncWithDependencies(null); synchronized (syncLocks) { syncLocks.remove(lockKey); } }, 1000); // 1秒延迟 } /** 带依赖关系的同步方法 根据 @RefTo 注解的依赖关系,确保: 双向关联的反向字段会同步更新 列表关联的所有元素会按顺序同步 单引用实体优先同步 @param callback 同步完成回调 */ public void syncWithDependencies(SyncCallback callback) { // 检测循环依赖 String entityKey = this.getClass().getName() + getId(); Set currentStack = syncStack.get(); if (currentStack.contains(entityKey)) { Log.w(“Sync”, "检测到循环依赖: " + entityKey); if (callback != null) callback.onSyncFailure(“循环依赖”); return; } currentStack.add(entityKey); state = SyncState.SYNCING; try { // 获取所有依赖实体 List dependencies = getDependencies(); if (dependencies.isEmpty()) { syncInternal(callback); return; } // 同步所有依赖实体 AtomicInteger counter = new AtomicInteger(dependencies.size()); for (Dependency dep : dependencies) { dep.entity.syncWithDependencies(new SyncCallback() { @Override public void onSyncSuccess(SynchronizableEntity entity) { // 处理双向关联的反向字段 if (dep.isBidirectional) { updateReverseField(dep, entity); } if (counter.decrementAndGet() == 0) { syncInternal(callback); } } @Override public void onSyncFailure(String error) { if (callback != null) { callback.onSyncFailure(error); } state = SyncState.MODIFIED; // 重置状态 } }); } } finally { currentStack.remove(entityKey); } } // 更新双向关联的反向字段 private void updateReverseField(Dependency dep, SynchronizableEntity updatedEntity) { try { Field reverseField = dep.targetType.getDeclaredField(dep.reverseFieldName); reverseField.setAccessible(true); if (dep.refType == RefType.SINGLE) { // 单引用反向设置 reverseField.set(updatedEntity, this); } else if (dep.refType == RefType.LIST) { // 列表引用反向添加 @SuppressWarnings("unchecked") List<SynchronizableEntity> list = (List<SynchronizableEntity>) reverseField.get(updatedEntity); if (list == null) { list = new ArrayList<>(); reverseField.set(updatedEntity, list); } if (!list.contains(this)) { list.add(this); } } } catch (Exception e) { Log.e("Sync", "更新反向字段失败", e); } } // 实际同步逻辑 private void syncInternal(SyncCallback callback) { switch (state) { case NEW: createToServer(callback); break; case MODIFIED: updateToServer(callback); break; case DELETED: deleteFromServer(callback); break; default: if (callback != null) callback.onSyncSuccess(this); } } // 依赖关系描述类 private static class Dependency { SynchronizableEntity entity; Class<?> targetType; RefType refType; boolean isBidirectional; String reverseFieldName; Dependency(SynchronizableEntity entity, Class<?> targetType, RefType refType, boolean isBidirectional, String reverseFieldName) { this.entity = entity; this.targetType = targetType; this.refType = refType; this.isBidirectional = isBidirectional; this.reverseFieldName = reverseFieldName; } } /** 获取所有依赖实体 根据 @RefTo 注解解析: target: 目标实体类型 type: 引用类型(SINGLE/LIST) bidirectional: 是否双向关联 reverseField: 反向字段名 */ private List getDependencies() { List dependencies = new ArrayList<>(); for (Field field : this.getClass().getDeclaredFields()) { try { field.setAccessible(true); RefTo refAnnotation = field.getAnnotation(RefTo.class); if (refAnnotation == null) continue; Object value = field.get(this); Class<?> targetType = refAnnotation.target(); RefType refType = refAnnotation.type(); boolean bidirectional = refAnnotation.bidirectional(); String reverseField = refAnnotation.reverseField(); if (refType == RefType.SINGLE && value instanceof SynchronizableEntity) { SynchronizableEntity entity = (SynchronizableEntity) value; if (entity.requiresSync()) { dependencies.add(new Dependency(entity, targetType, refType, bidirectional, reverseField)); } } else if (refType == RefType.LIST && value instanceof List) { for (Object item : (List<?>) value) { if (item instanceof SynchronizableEntity) { SynchronizableEntity entity = (SynchronizableEntity) item; if (entity.requiresSync()) { dependencies.add(new Dependency(entity, targetType, refType, bidirectional, reverseField)); } } } } } catch (Exception e) { Log.e(“Sync”, “获取依赖失败”, e); } } // 确保单引用实体优先同步 dependencies.sort((d1, d2) -> { if (d1.refType == RefType.SINGLE && d2.refType != RefType.SINGLE) return -1; if (d1.refType != RefType.SINGLE && d2.refType == RefType.SINGLE) return 1; return 0; }); return dependencies; } // 错误处理(带重试机制) private void handleSyncError(String error, SyncCallback callback) { if (retryCount < MAX_RETRY) { retryCount++; new Handler(Looper.getMainLooper()).postDelayed(() -> syncWithDependencies(callback), 3000); } else { state = SyncState.MODIFIED; retryCount = 0; if (callback != null) callback.onSyncFailure(error); } } // 检查是否需要同步 boolean requiresSync() { return state == SyncState.NEW || state == SyncState.MODIFIED || state == SyncState.DELETED; } // 同步回调接口 public interface SyncCallback { void onSyncSuccess(SynchronizableEntity entity); void onSyncFailure(String error); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; return Objects.equals(getId(), ((SynchronizableEntity) o).getId()); } } 2025-06-18 03:12:48.740 2387-2387 AddInventoryFragment com.example.kucun2 D createAndSaveDingdan: {“dingdanChanpin”:[],“dingdanChanpinZujian”:[],“id”:10002,“jiaohuo”:{},“number”:“mjjj”,“xiadan”:{},“changeSupport”:null,“propertyCache”:{},“retryCount”:0,“state”:{}} 2025-06-18 03:12:48.741 2387-2387 SynchronizedList com.example.kucun2 D 娣诲姞瀹炰綋: com.example.kucun2.entity.Dingdan@cf68912, 鐘舵��: NEW 2025-06-18 03:12:48.741 2387-2387 SynchronizedList com.example.kucun2 D 瑙﹀彂鑷姩鍚屾: com.example.kucun2.entity.Dingdan@cf68912 2025-06-18 03:12:48.741 2387-2387 SynchronizedList com.example.kucun2 D 瀹夋帓鑷姩鍚屾: com.example.kucun2.entity.Dingdan@cf68912 2025-06-18 03:12:48.741 2387-2387 SynchronizedList com.example.kucun2 D 鎵ц鍚屾: com.example.kucun2.entity.Dingdan@cf68912, 鏄惁鍦ㄥ垪琛ㄤ腑: true 2025-06-18 03:12:48.742 2387-2387 SynchronizedList com.example.kucun2 I 鍚屾鎴愬姛: com.example.kucun2.entity.Dingdan@cf68912 2025-06-18 03:12:48.750 2387-2387 WindowOnBackDispatcher com.example.kucun2 W sendCancelIfRunning: isInProgress=false callback=android.view.ViewRootImpl$$ExternalSyntheticLambda11@3655af2 2025-06-18 03:12:48.765 2387-5861 HWUI com.example.kucun2 D endAllActiveAnimators on 0xb4000070500a5200 (RippleDrawable) with handle 0xb4000070d0083e10 2025-06-18 03:12:48.829 2387-2387 ImeFocusController com.example.kucun2 V onWindowFocus: com.android.internal.policy.DecorView{34ec7ae V.E… R…D 0,0-1260,2800 aid=0}[MainActivity] softInputMode=STATE_UNSPECIFIED|ADJUST_RESIZE 2025-06-18 03:12:48.847 2387-2387 InsetsController com.example.kucun2 D hide(ime(), fromIme=true) 2025-06-18 03:12:48.848 2387-2387 ImeTracker com.example.kucun2 I com.example.kucun2:ea0ea6b1: onCancelled at PHASE_CLIENT_APPLY_ANIMATION 2025-06-18 03:12:48.848 2387-2387 ImeBackDispatcher com.example.kucun2 E Ime callback not found. Ignoring unregisterReceivedCallback. callbackId: 31607086同步不触发,获取url日志没显示,后端也没收到信息
最新发布
06-19
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值