package com.example.tyre; import android.app.ProgressDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.android.hdhe.uhf.reader.UhfReader; import com.android.hdhe.uhf.readerInterface.TagModel; import com.example.tyre.entity.AjaxResult; import com.example.tyre.entity.BaseTyre; import com.example.tyre.entity.EPC; import com.example.tyre.entity.InStoreSpinnerVo; import com.example.tyre.entity.Tyre; import com.example.tyre.entity.TyreSizeVo; import com.example.tyre.util.CommonDialog; import com.example.tyre.util.MyUrl; import com.example.tyre.util.SharedPreferencesUtils; import com.example.tyre.util.Util; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import com.lzy.okgo.OkGo; import com.lzy.okgo.callback.StringCallback; import com.lzy.okgo.model.Response; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; import cn.pda.serialport.Tools; /** * 轮胎入库管理 Activity (优化版) * 适配重构后的 XML 布局,解决下拉框重影与数据绑定问题 */ public class InStoreHouseActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener { // === UI 组件绑定 (基于新布局修正) === @BindView(R.id.button) Button button; @BindView(R.id.back) Button back; // 1. EPC 相关:原 @BindView(R.id.epc) 是 TextView,现在建议直接读取显示文本或维护内部变量 // 假设 XML 中 Spinner EPC 的 ID 是 spinnerEPC (根据上一轮修改) @BindView(R.id.EPC) TextView EPC; // 2. 胎号 (EditText) @BindView(R.id.wtbm) EditText wtbm; // 3. 花纹深度 (EditText) @BindView(R.id.patternDepth) EditText patternDepth; // 4. 下拉框 Spinners (核心修复点) @BindView(R.id.spinnerkind) Spinner spinnerkind; @BindView(R.id.spinnerpattern) Spinner spinnerpattern; @BindView(R.id.spinnerlevel) Spinner spinnerlevel; @BindView(R.id.spinnerSize) Spinner spinnerSize; @BindView(R.id.spinnerBrand) Spinner spinnerBrand; @BindView(R.id.spinnergcts) Spinner spinnergcts; // === 内部数据变量 (用于保存选中的值) === // 注意:不再需要 pinpai, xinghao 等 TextView 的 BindView // 我们直接通过 Spinner.getSelectedItem().toString() 获取值 // 或者定义变量保存 private String selectedBrand = ""; private String selectedModel = ""; private String selectedLevel = ""; private String selectedPattern = ""; private String selectedKind = ""; private String selectedGcts = ""; // === 业务逻辑变量 === private boolean isStart = true; private ProgressDialog progressDialog; private boolean runFlag = true; private boolean startFlag = false; private UhfReader manager; private ArrayList listEPC; private ArrayList listepc = new ArrayList(); private List patternSize; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_instorehouse); // 确保使用新布局 ButterKnife.bind(this); manager = MyApplication.getManager(); initView(); // 初始化下拉框数据 check_spinner(); // 启动 UHF 扫描线程 Thread thread = new InventoryThread(); thread.start(); Util.initSoundPool(this); } private void initView() { listEPC = new ArrayList(); // 初始化所有 Spinner 的监听器 initSpinners(); } /** * 统一初始化所有 Spinner 的监听器 * 避免代码重复 */ private void initSpinners() { spinnerkind.setOnItemSelectedListener(this); spinnerpattern.setOnItemSelectedListener(this); spinnerlevel.setOnItemSelectedListener(this); spinnerSize.setOnItemSelectedListener(this); spinnerBrand.setOnItemSelectedListener(this); spinnergcts.setOnItemSelectedListener(this); } @Override public void onResume() { super.onResume(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } registerReceiver(); startFlag = false; // 开启扫描 } @Override public void onPause() { startFlag = false; super.onPause(); unregisterReceiver(); } @Override protected void onDestroy() { runFlag = false; super.onDestroy(); } // === UHF 扫描逻辑优化 === class InventoryThread extends Thread { @Override public void run() { while (runFlag) { if (startFlag) { List tagList = manager.inventoryRealTime(); if (tagList != null && !tagList.isEmpty()) { Util.play(1, 0); // 播放提示音 for (TagModel tag : tagList) { String epcStr = tag == null ? "" : Tools.Bytes2HexString(tag.getmEpcBytes(), tag.getmEpcBytes().length); byte rssi = tag != null ? tag.getmRssi() : -1; addToList(epcStr, rssi); } // 防止频繁刷新 try { Thread.sleep(20); } catch (InterruptedException e) { } } } } } } /** * 处理扫描到的 EPC 标签 * 优化:直接操作数据,更新 UI */ private void addToList(final String epc, final byte rssi) { runOnUiThread(new Runnable() { @Override public void run() { // 1. 更新 EPC 显示 (直接设置到 Spinner 或 TextView) // 假设 spinnerEPC 是用来显示 EPC 的 // 这里可能需要一个只读的 Adapter 或者直接 setText (如果 spinnerEPC 改为了 TextView) // 为了简化,假设我们有一个方法更新 EPC 显示 //updateEpcDisplay(epc); EPC.setText(epc); // 2. 清理旧数据 (根据业务逻辑调整,通常不建议每次扫描都清空) listepc.clear(); listepc.add(epc); // 3. 自动查询后台数据 if (!epc.isEmpty()) { find(epc); startFlag = false; // 扫描到一次后暂停,防止重复提交 } } }); } private void updateEpcDisplay(String epc) { // 这里根据你的实际布局调整 // 如果 spinnerEPC 是 Spinner,你可能需要一个包含该 EPC 的 Adapter // 或者在 XML 中保留一个隐藏的 EditText 用于传参 // 简单处理:打印日志 Log.d("UHF", "Scanned EPC: " + epc); } // === 网络请求与数据填充 === private void find(String epc) { showLoadingDialog(); OkGo.post(MyUrl.url + "/tyre/tyre/pdaQueryTyreInfo") .tag(this) .params("tyreEpc", epc) .execute(new StringCallback() { @Override public void onSuccess(Response response) { hideLoadingDialog(); try { Gson gson = new Gson(); BaseTyre baseTyre = gson.fromJson(response.body(), BaseTyre.class); if (baseTyre != null) { // 填充表单数据 // 注意:这里不再 setText 到被移除的 TextView // 而是应该选中 Spinner 的对应项,或者填充 EditText wtbm.setText(safeGetString(baseTyre.getTyreNo())); // 逻辑优化:Spinner 应该通过 Adapter 选中 position // 这里简化处理,直接记录值供提交使用 selectedBrand = safeGetString(baseTyre.getTyreBrand()); selectedModel = safeGetString(baseTyre.getTyreModel()); selectedLevel = safeGetString(baseTyre.getTyreLevel()); selectedPattern = safeGetString(baseTyre.getTyrePattern()); selectedKind = safeGetString(baseTyre.getTyreType()); // 如果需要自动选中 Spinner,需要遍历 Adapter 寻找 position // setSelectedSpinnerItem(spinnerBrand, selectedBrand); }else { wtbm.setText(""); } } catch (Exception e) { e.printStackTrace(); } } }); } private String safeGetString(String value) { // 注意:原代码中有一行是 "null".equals(value),这是为了防止后台返回字符串 "null" return value == null || "null".equals(value) ? "" : value; } // === 提交逻辑 === @OnClick({R.id.button, R.id.back}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.button: submitData(); break; case R.id.back: finish(); // 推荐使用 finish 返回 break; } } private void submitData() { // 1. 获取当前显示的值 // String epc = ((TextView) spinnerEPC.getChildAt(0)).getText().toString(); // 复杂 // 简单方案:假设你有一个变量保存了最后扫描的 EPC String currentEpc = getCurrentEpcFromUHF(); // 你需要实现这个逻辑或维护一个变量 if (currentEpc.isEmpty()) { new CommonDialog(this).setMessage("请扫描轮胎芯片!").show(); return; } String wtbmStr = wtbm.getText().toString().trim(); String depthStr = patternDepth.getText().toString().trim(); // 2. 获取下拉框选中的值 (核心修复) // 由于去除了重影 TextView,直接从 Spinner 获取 String brand = spinnerBrand.getSelectedItem() != null ? spinnerBrand.getSelectedItem().toString() : selectedBrand; String model = spinnerSize.getSelectedItem() != null ? spinnerSize.getSelectedItem().toString() : selectedModel; String level = spinnerlevel.getSelectedItem() != null ? spinnerlevel.getSelectedItem().toString() : selectedLevel; String pattern = spinnerpattern.getSelectedItem() != null ? spinnerpattern.getSelectedItem().toString() : selectedPattern; String kind = spinnerkind.getSelectedItem() != null ? spinnerkind.getSelectedItem().toString() : selectedKind; String grooves = spinnergcts.getSelectedItem() != null ? spinnergcts.getSelectedItem().toString() : selectedGcts; // 3. 参数校验 if (wtbmStr=="" || wtbmStr == null || wtbmStr == "Scan fail") { new CommonDialog(this).setMessage("胎号不能为空").show(); return; } showLoadingDialog(); // 4. 发送网络请求 OkGo.post(MyUrl.url + "/tyre/inventory/pdaAddInventory") .tag(this) .params("tyreRfid", currentEpc) .params("tyreEpc", currentEpc) .params("tyreOutsideId", wtbmStr) .params("tyreBrand", brand) .params("tyreModel", model) .params("tyreLevel", level) .params("tyrePattern", pattern) .params("grooves", grooves) .params("tyreType", kind) .params("patternDepth", depthStr) .params("CreateBy", SharedPreferencesUtils.getstring("user", "admin")) .execute(new StringCallback() { @Override public void onSuccess(Response response) { hideLoadingDialog(); handleResponse(response.body()); } @Override public void onError(Response response) { hideLoadingDialog(); Toast.makeText(InStoreHouseActivity.this, "请求失败,请检查网络", Toast.LENGTH_SHORT).show(); } }); } private String getCurrentEpcFromUHF() { // TODO: 实现获取当前扫描到的 EPC 的逻辑 // 例如返回 listepc.get(0) 或者维护一个全局变量 currentEpc return listepc.isEmpty() ? "" : listepc.get(0); } private void handleResponse(String body) { try { AjaxResult result = new Gson().fromJson(body, AjaxResult.class); new CommonDialog(this).setMessage(result.getMsg()).show(); if ("200".equals(result.getCode())) { // 假设 200 是成功 // 清空数据以便下一次扫描 clearForm(); } } catch (Exception e) { Toast.makeText(this, "数据解析错误", Toast.LENGTH_SHORT).show(); } } private void clearForm() { wtbm.setText(""); patternDepth.setText(""); EPC.setText(""); // spinnerEPC... 清空逻辑 } // === 下拉框数据加载 (保持不变,但 Adapter 绑定逻辑需确认) === private void check_spinner() { showLoadingDialog(); OkGo.post(MyUrl.url + "/system/dict/data/tyreTypeList") .execute(new StringCallback() { @Override public void onSuccess(Response response) { try { Gson gson = new Gson(); InStoreSpinnerVo vo = gson.fromJson(response.body(), InStoreSpinnerVo.class); // 设置 Adapter (逻辑保持不变) setAdapter(spinnerkind, vo.getKindList()); setAdapter(spinnerpattern, vo.getPatternList()); setAdapter(spinnerlevel, vo.getLevelList()); setAdapter(spinnergcts, vo.getGctsList()); setAdapter(spinnerBrand, vo.getTyreBrandList()); // 特殊处理:型号 (需要处理 Label/Value) List sizeLabels = new ArrayList<>(); if (vo.getTyreSizeList() != null) { patternSize = vo.getTyreSizeList(); for (TyreSizeVo size : patternSize) { sizeLabels.add(size.getLabel()); } } setAdapter(spinnerSize, sizeLabels); hideLoadingDialog(); } catch (Exception e) { e.printStackTrace(); } } }); } private void setAdapter(Spinner spinner, List data) { if (data != null && !data.isEmpty()) { ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, data); spinner.setAdapter(adapter); } } // === Spinner 选择监听 (优化版) === @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { // 仅保存选中的值,不再 setText 到任何 TextView (解决重影的根本原因) String selectedItem = parent.getItemAtPosition(position).toString(); switch (parent.getId()) { case R.id.spinnerBrand: selectedBrand = selectedItem; break; case R.id.spinnerSize: selectedModel = selectedItem; // 如果需要根据型号联动花纹深度 if (patternSize != null && position < patternSize.size()) { patternDepth.setText(patternSize.get(position).getValue()); } break; case R.id.spinnerlevel: selectedLevel = selectedItem; break; case R.id.spinnerpattern: selectedPattern = selectedItem; break; case R.id.spinnerkind: selectedKind = selectedItem; break; case R.id.spinnergcts: selectedGcts = selectedItem; break; } } @Override public void onNothingSelected(AdapterView parent) { // 可选:设置默认值 } // === 广播接收器 (保持不变) === private KeyReceiver keyReceiver; private void registerReceiver() { keyReceiver = new KeyReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction("android.rfid.FUN_KEY"); filter.addAction("android.intent.action.FUN_KEY"); registerReceiver(keyReceiver, filter); } private void unregisterReceiver() { if (keyReceiver != null) { unregisterReceiver(keyReceiver); keyReceiver = null; } } private class KeyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { int keyCode = intent.getIntExtra("keyCode", 0); if (keyCode == 0) keyCode = intent.getIntExtra("keycode", 0); boolean keyDown = intent.getBooleanExtra("keydown", false); switch (keyCode) { case KeyEvent.KEYCODE_F1: case KeyEvent.KEYCODE_F2: case KeyEvent.KEYCODE_F3: case KeyEvent.KEYCODE_F4: case KeyEvent.KEYCODE_F5: //扫描 startFlag = true; break; } } } private void showLoadingDialog() { if (progressDialog == null) { progressDialog = new ProgressDialog(this); progressDialog.setMessage("数据加载中..."); progressDialog.setCancelable(false); // 禁止用户通过返回键取消 } if (!progressDialog.isShowing()) { progressDialog.show(); } } /** * 隐藏加载对话框 */ private void hideLoadingDialog() { if (progressDialog != null && progressDialog.isShowing()) { progressDialog.dismiss(); } } }