java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to java.lang.Int

异常:java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to java.lang.Integer
原因:SQL查询结果为count()统计结果个数,gson返回数据为json格式,不能直接转换为基本数据类型。
解决:在查询SQL中未结果字段设置别名count(
) as count,在gson返回数据中以Map<String,Integer>接收,之后从map中get(“count”)即可。

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”); Log.d(TAG, "创建端点: " + endpoint); ApiClient.post(endpoint, this, new ApiClient.ApiCallback<SynchronizableEntity>() { @Override public void onSuccess(SynchronizableEntity responseData) { if (responseData != null) { setId(responseData.getId()); } 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(); ApiClient.put(endpoint, this, new ApiClient.ApiCallback<SynchronizableEntity>() { @Override public void onSuccess(SynchronizableEntity responseData) { 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”); // 创建删除请求对象(包含ID) ApiClient.delete(endpoint, this, new ApiClient.ApiCallback<Void>() { @Override public void onSuccess(Void data) { 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()); } } E FATAL EXCEPTION: OkHttp Dispatcher Process: com.example.kucun2, PID: 9074 java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.example.kucun2.entity.data.SynchronizableEntity at com.example.kucun2.entity.data.SynchronizableEntity$ 1.onSuccess(SynchronizableEntity.java:137) at com.example.kucun2.entity.data.ApiClient$ 1.onResponse(ApiClient.java:62) at okhttp3.RealCall$ AsyncCall.execute(RealCall.java:174) at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$ Worker.run(ThreadPoolExecutor.java:644) at java.lang.Thread.run(Thread.java:1042) 2025-06-18 23:20:52.449 9074-12671 Process com.example.kucun2 I Sending signal. PID: 9074 SIG: 9 Type responseType = new TypeToken<Information<T>>() {}.getType();不管用?为毛会要解析为SynchronizableEntity
06-19
package com.example.kucun2.entity.data; import android.util.Log; import androidx.annotation.NonNull; import com.google.gson.Gson; import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Proxy; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Objects; import java.util.Set; import okhttp3.Call; import okhttp3.Callback; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; /** * 支持数据变更自动同步的泛型集合类 * @param <T> 继承自 SynchronizableEntity 的实体类型 */ public class SynchronizedList<T extends SynchronizableEntity> implements List<T> { private final List<T> list = new ArrayList<>(); private final OkHttpClient client = new OkHttpClient(); private static final Gson gson = new Gson(); private static final MediaType JSON = MediaType.get("application/json; charset=utf-8"); private final Class<T> entityClass; // 类型标记 // 添加批量操作模式标志 private boolean batchMode = false; // 属性变更监听器 private final List<PropertyChangeListener<T>> listeners = new ArrayList<>(); // 直接接受Class参数的构造函数 public SynchronizedList(Class<T> entityClass) { this.entityClass = entityClass; } // 安全的类型转换方法 private T safeCast(Object o) { if (o != null && entityClass.isInstance(o)) { return entityClass.cast(o); } return null; } public interface PropertyChangeListener<T> { void onPropertyChange(T entity, String propertyName, Object oldValue, Object newValue); } public void addPropertyChangeListener(PropertyChangeListener<T> listener) { listeners.add(listener); } public void removePropertyChangeListener(PropertyChangeListener<T> listener) { listeners.remove(listener); } // 添加方法来获取原始对象 @SuppressWarnings("unchecked") public T getOriginal(T proxy) { if (proxy == null) return null; // 检查是否为代理对象 if (java.lang.reflect.Proxy.isProxyClass(proxy.getClass())) { try { java.lang.reflect.InvocationHandler handler = java.lang.reflect.Proxy.getInvocationHandler(proxy); if (handler instanceof IProxyHandler) { Object original = ((IProxyHandler) handler).getOriginal(); // 安全类型检查 if (entityClass.isInstance(original)) { return (T) original; } } } catch (Exception e) { Log.e("SynchronizedList", "Failed to get proxy handler", e); } } return proxy; } /** * 同步实体到后端 * * @param entity 要同步的实体 */ private void syncEntity(T entity) { if (batchMode) return; String operation = "add"; T originalEntity = getOriginal(entity); String endpoint = originalEntity.getEndpoint(operation); String json = gson.toJson(originalEntity); RequestBody body = RequestBody.create(json, JSON); Request request = new Request.Builder() .url(endpoint) .method(getHttpMethod(operation), body) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { Log.e("SynchronizedList", "同步失败: " + entity.getClass().getSimpleName(), e); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) { if (!response.isSuccessful()) { Log.e("SynchronizedList", "同步失败: " + response.code() + " - " + response.message()); } response.close(); } }); } // 添加用于批量操作的方法 public void beginBatch() { this.batchMode = true; } public void endBatch() { this.batchMode = false; // 批量结束后触发一次全量同步 syncAllEntities(); } private void syncAllEntities() { for (T entity : list) { syncEntity(entity); } } private String getHttpMethod(String operation) { switch (operation) { case "add": return "POST"; case "update": return "PUT"; case "delete": return "DELETE"; default: return "POST"; } } // 获取类实现的所有接口(包括父类接口) private Class<?>[] getInterfaces(Class<?> clazz) { Set<Class<?>> interfaces = new HashSet<>(); while (clazz != null) { interfaces.addAll(Arrays.asList(clazz.getInterfaces())); clazz = clazz.getSuperclass(); } return interfaces.toArray(new Class<?>[0]); } /** * 创建代理对象,用于监听属性变更 */ // 优化 createProxy 方法 private T createProxy(T original) { if (original == null) return null; // 确保代理对象实现原始对象的所有接口+目标接口 Class<?>[] interfaces = new Class<?>[]{ SynchronizableEntity.class, // 强制实现目标接口 entityClass // 实体类或接口 }; // 使用动态代理实现接口 return (T) Proxy.newProxyInstance( original.getClass().getClassLoader(), new Class<?>[] { EntityClassGrassrootsid.class }, // 只代理接口 new EntityProxyHandler(original) ); // if (!entityClass.isInstance(original)) { // throw new IllegalArgumentException("Invalid entity type"); // } // // 这里使用动态代理模式监听setter方法调用 // return (T) java.lang.reflect.Proxy.newProxyInstance( // original.getClass().getClassLoader(), // original.getClass().getInterfaces(), // (proxy, method, args) -> { // // 只拦截setter方法 // if (method.getName().startsWith("set") && args.length == 1) { // String propertyName = method.getName().substring(3); // propertyName = propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1); // // // 获取旧值 // Object oldValue = original.getClass() // .getMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1)) // .invoke(original); // // // 调用原始方法 // Object result = method.invoke(original, args); // // // 触发监听器 // for (PropertyChangeListener<T> listener : listeners) { // listener.onPropertyChange(original, propertyName, oldValue, args[0]); // } // // // 自动同步到后端 // syncEntity(original); // return result; // } // return method.invoke(original, args); // } // ); } // 以下是List接口的实现 @Override public int size() { return list.size(); } @Override public boolean isEmpty() { return list.isEmpty(); } @Override public boolean contains(Object o) { return list.contains(o); } @NonNull @Override public Iterator<T> iterator() { return list.iterator(); } @NonNull @Override public Object[] toArray() { return list.toArray(); } @NonNull @Override public <T1> T1[] toArray(@NonNull T1[] a) { return list.toArray(a); } @Override public boolean add(T t) { T proxy = createProxy(t); boolean result = list.add(proxy); if (!batchMode) { syncEntity(proxy); } return result; // 添加时创建代理 } @Override public boolean remove(Object o) { T entity = safeCast(o); if (entity != null) { syncEntity((T) entity); // 删除前同步 } return list.remove(o); } @Override public boolean containsAll(@NonNull Collection<?> c) { return list.containsAll(c); } @Override public boolean addAll(@NonNull Collection<? extends T> c) { boolean modified = false; for (T t : c) { modified |= add(t); } return modified; } @Override public boolean addAll(int index, @NonNull Collection<? extends T> c) { for (T t : c) { add(index++, t); } return true; } @Override public boolean removeAll(@NonNull Collection<?> c) { for (Object o : c) { T entity = safeCast(o); if (entity != null) { syncEntity(entity); } } return list.removeAll(c); } @Override public boolean retainAll(@NonNull Collection<?> c) { List<T> toRemove = new ArrayList<>(); for (T t : list) { if (!c.contains(t)) { toRemove.add(t); } } // 使用安全转换 for (T entity : toRemove) { syncEntity(entity); } return list.retainAll(c); } @Override public void clear() { for (T t : list) { syncEntity(t); // 清空前同步 } list.clear(); } @Override public T get(int index) { return list.get(index); } @Override public T set(int index, T element) { T old = list.set(index, createProxy(element)); if (old != null) { syncEntity(old); // 替换旧元素前同步 } return old; } @Override public void add(int index, T element) { list.add(index, createProxy(element)); } @Override public T remove(int index) { T removed = list.remove(index); if (removed != null) { syncEntity(removed); // 删除前同步 } return removed; } @Override public int indexOf(Object o) { return list.indexOf(o); } @Override public int lastIndexOf(Object o) { return list.lastIndexOf(o); } @NonNull @Override public ListIterator<T> listIterator() { return list.listIterator(); } @NonNull @Override public ListIterator<T> listIterator(int index) { return list.listIterator(index); } @NonNull @Override public List<T> subList(int fromIndex, int toIndex) { return list.subList(fromIndex, toIndex); } // 触发属性变更通知 // 添加类型安全的属性监听 private void firePropertyChange(T entity, String propertyName, Object oldValue, Object newValue) { if (oldValue != null && newValue != null && oldValue.equals(newValue)) { return; // 值未变化时不触发监听 } for (PropertyChangeListener<T> listener : listeners) { try { listener.onPropertyChange(entity, propertyName, oldValue, newValue); } catch (Exception e) { Log.e("SynchronizedList", "Listener error", e); } } } // 修改代理处理器以支持获取原始对象 /* 完整的 EntityProxyHandler 实现 */ private class EntityProxyHandler implements IProxyHandler, java.lang.reflect.InvocationHandler { private final T original; private final Map<String, Object> propertyValues = new HashMap<>(); public EntityProxyHandler(T original) { this.original = original; cachePropertyValues(); } private void cachePropertyValues() { // 获取类信息 Class<?> clazz = original.getClass(); // 遍历所有getter方法 for (Method method : clazz.getMethods()) { String methodName = method.getName(); // 只处理getter方法 if (methodName.startsWith("get") && !methodName.equals("getClass") && method.getParameterTypes().length == 0) { try { // 获取属性名(去掉"get"并将首字母小写) String propertyName = methodName.substring(3); propertyName = Character.toLowerCase(propertyName.charAt(0)) + propertyName.substring(1); // 调用getter获取值 Object value = method.invoke(original); propertyValues.put(propertyName, value); } catch (Exception e) { Log.e("Wrapper", "Failed to cache property " + methodName, e); } } } } @Override public T getOriginal() { return original; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); // 只拦截setter方法 if (methodName.startsWith("set") && args != null && args.length == 1) { String propertyName = methodName.substring(3); propertyName = Character.toLowerCase(propertyName.charAt(0)) + propertyName.substring(1); Object oldValue = propertyValues.get(propertyName); Object newValue = args[0]; // 如果值未改变,不触发同步 if (Objects.equals(oldValue, newValue)) { return null; } // 调用原始对象的setter方法 Method setter = original.getClass().getMethod(methodName, newValue.getClass()); setter.invoke(original, newValue); // 更新属性缓存 propertyValues.put(propertyName, newValue); // 触发属性变更监听 firePropertyChange(original, propertyName, oldValue, newValue); // 非批量模式下自动同步 if (!batchMode) { syncEntity(original); } } // 其他接口方法直接调用原始对象 return method.invoke(original, args); } private Object getPropertyValue(String propertyName) { String getterName = "get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1); try { Method getter = original.getClass().getMethod(getterName); return getter.invoke(original); } catch (Exception e) { Log.e("ProxyHandler", "Failed to get property value: " + propertyName, e); return null; } } } // 在 SynchronizedList 类中添加 private interface IProxyHandler { Object getOriginal(); } }package com.example.kucun2.entity; import android.annotation.SuppressLint; import com.example.kucun2.entity.data.SynchronizableEntity; import java.util.Objects; //板材 public class Bancai extends SynchronizableEntity { private Integer id; private Caizhi caizhi; private Mupi mupi1; private Mupi mupi2; private Double houdu; public Bancai() { } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Bancai bancai = (Bancai) o; return Objects.equals(id, bancai.id) && Objects.equals(caizhi, bancai.caizhi) && Objects.equals(mupi1, bancai.mupi1) && Objects.equals(mupi2, bancai.mupi2) && Objects.equals(houdu, bancai.houdu); } @Override public int hashCode() { return Objects.hash(id, caizhi, mupi1, mupi2, houdu); } public Bancai(Integer id, Caizhi caizhi, Mupi mupi1, Mupi mupi2, Double houdu) { this.id = id; this.caizhi = caizhi; this.mupi1 = mupi1; this.mupi2 = mupi2; this.houdu = houdu; } public Integer getId() { return id; } public Caizhi getCaizhi() { return caizhi; } public Mupi getMupi1() { return mupi1; } public Mupi getMupi2() { return mupi2; } public Double getHoudu() { return houdu; } public void setId(Integer id) { this.id = id; } public void setCaizhi(Caizhi caizhi) { this.caizhi = caizhi; if (caizhi!=null&&caizhi.getBancais()!=null){ this.caizhi.getBancais().add(this); } } public void setMupi1(Mupi mupi1) { this.mupi1 = mupi1; if (mupi1!=null&&mupi1.getBancais()!=null){ this.mupi1.getBancais().add(this); } } public void setMupi2(Mupi mupi2) { this.mupi2 = mupi2; if (mupi2!=null&&mupi2.getBancais()!=null){ this.mupi2.getBancais().add(this); } } public void setHoudu(Double houdu) { this.houdu = houdu; } /** * 表格中显示的文字 * @return */ @SuppressLint("DefaultLocale") public String TableText(){ String boardInfo=""; boardInfo +=String.format("%.1f", this.getHoudu())+this.getCaizhi().getName()+"("; if (mupi1 != null) { boardInfo += (this.getMupi1().getYou()?this.getMupi1().getName()+"油":this.getMupi1().getName()); } if (mupi2 != null&&mupi1 != null) { boardInfo+=","; } if (mupi2 != null) { boardInfo += (this.getMupi2().getYou()?this.getMupi2().getName()+"油":this.getMupi2().getName()); } boardInfo+=")"; return boardInfo; } } package com.example.kucun2.entity.data; import com.example.kucun2.function.MyAppFnction; public abstract class SynchronizableEntity implements EntityClassGrassrootsid { /** * 添加url * @param type 操作增删改查 * @return 返回相对url */ public String getEndpoint(String type){ //从String.xml获取url return MyAppFnction.getStringResource("String","url_"+type+"_"+this.getClass().getSimpleName()); } } package com.example.kucun2.ui.jinhuo; import static android.content.ContentValues.TAG; import android.app.AlertDialog; import android.app.DatePickerDialog; 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.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.MultiAutoCompleteTextView; import android.widget.RadioGroup; import android.widget.SearchView; import android.widget.Spinner; import android.widget.TextView; 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.entity.data.Data; import com.example.kucun2.function.Adapter; import com.google.android.material.textfield.TextInputEditText; 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.Random; public class AddInventoryFragment extends Fragment { private Spinner spinnerDingdan, spinnerChanpin, spinnerZujian, spinnerBancai; private EditText etShuliang; private RadioGroup rgType; private Dingdan selectedDingdan; private Chanpin selectedChanpin; private Zujian selectedZujian; private Bancai selectedBancai; // 创建新订单产品组件按钮 private Button btnNewDingdan, btnAddChanpin, btnAddZujian; // 日期格式化 private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); /** * 初始化 * @param inflater The LayoutInflater object that can be used to inflate * any views in the fragment, * @param container If non-null, this is the parent view that the fragment's * UI should be attached to. The fragment should not add the view itself, * but this can be used to generate the LayoutParams of the view. * @param savedInstanceState If non-null, this fragment is being re-constructed * from a previous saved state as given here. * * @return */ @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_add_inventory, container, false); // 初始化UI组件 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); Button btnSubmit = view.findViewById(R.id.btn_submit); // 初始化新按钮 btnNewDingdan = view.findViewById(R.id.btn_new_dingdan); btnAddChanpin = view.findViewById(R.id.btn_add_chanpin); btnAddZujian = view.findViewById(R.id.btn_add_zujian); // 设置按钮点击事件 btnNewDingdan.setOnClickListener(v -> createNewDingdan()); btnAddChanpin.setOnClickListener(v -> showAddChanpinDialog()); btnAddZujian.setOnClickListener(v -> addZujianToChanpin()); // 设置订单选择器 setupDingdanSpinner(); // 提交按钮点击事件 btnSubmit.setOnClickListener(v -> addInventoryRecord()); return view; } private void setupDingdanSpinner() { Adapter.setupDingdanSpinner(spinnerDingdan,Data.dingdans,getContext()); 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<>(); for (Dingdan_Chanpin dc : dingdan.getChanpins()) { 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); setupZujianSpinner(selectedChanpin); } @Override public void onNothingSelected(AdapterView<?> parent) {} }); } /** * 组件下拉框刷新 * @param chanpin */ private void setupZujianSpinner(Chanpin chanpin) { // 获取该产品的组件列表 List<Zujian> zujians = new ArrayList<>(); for (Chanpin_Zujian cz : chanpin.getZujians()) { 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) {} }); } /** * 板材刷新 * @param chanpin * @param zujian */ private void setupBancaiSpinner(Chanpin chanpin, Zujian zujian) { // 获取该组件关联的板材 List<Bancai> bancais = new ArrayList<>(); for (Chanpin_Zujian cz : chanpin.getZujians()) { 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); } @Override public void onNothingSelected(AdapterView<?> parent) {} }); } // ... addInventoryRecord和createRecord方法保持不变 ... private void addInventoryRecord() { // 验证必填项 if (selectedDingdan == null || selectedChanpin == null || selectedZujian == null || selectedBancai == null) { 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; } // 解析数量 int shuliang; try { shuliang = Integer.parseInt(shuliangStr); } catch (NumberFormatException e) { Toast.makeText(getContext(), "请输入有效的数量", Toast.LENGTH_SHORT).show(); return; } // 确定操作类型(进货或消耗) boolean isJinhuo = rgType.getCheckedRadioButtonId() == R.id.rb_jinhuo; // 实际开发中应从登录信息获取当前用户 User currentUser = new User(1, "当前用户", "user", "password",1); // 创建记录 createRecord(selectedDingdan, selectedChanpin, selectedZujian, selectedBancai, shuliang, isJinhuo, currentUser); Toast.makeText(getContext(), "记录添加成功", Toast.LENGTH_SHORT).show(); etShuliang.setText(""); // 清空输入框 } private void createRecord(Dingdan dingdan, Chanpin chanpin, Zujian zujian, Bancai bancai, int shuliang, boolean isJinhuo, User user) { if (isJinhuo) { // 创建进货记录 Jinhuo jinhuo = new Jinhuo(); jinhuo.setId(Data.jinhuoList.size() + 1); jinhuo.setDingdan(dingdan); jinhuo.setChanpin(chanpin); jinhuo.setZujian(zujian); jinhuo.setBancai(bancai); jinhuo.setShuliang(shuliang); jinhuo.setDate(new Date()); jinhuo.setUser(user); Data.jinhuoList.add(jinhuo); } else { // 消耗数量转为负数 shuliang = -shuliang; } // 更新库存 updateKucun(bancai, shuliang); } private void updateKucun(Bancai bancai, int changeAmount) { // 查找现有库存记录 for (Kucun k : Data.kucuns) { if (k.getBancai().getId().equals(bancai.getId())) { k.setShuliang(k.getShuliang() + changeAmount); return; } } // 如果没有找到库存记录,创建新的 Kucun newKucun = new Kucun(); newKucun.setId(Data.kucuns.size() + 1); newKucun.setBancai(bancai); newKucun.setShuliang(Math.max(changeAmount, 0)); // 确保不为负 Data.kucuns.add(newKucun); } // 新建订单方法 private void createNewDingdan() { showNewDingdanDialog(); } /** * 向订单添加产品 * @param chanpin */ private void addChanpinToDingdan(Chanpin chanpin) { if (selectedDingdan == null) { Toast.makeText(getContext(), "请先选择订单", Toast.LENGTH_SHORT).show(); return; } // 检查产品是否已在订单中 for (Dingdan_Chanpin dc : selectedDingdan.getChanpins()) { if (dc.getChanpin().getId().equals(chanpin.getId())) { Toast.makeText(getContext(), "该产品已添加到订单", Toast.LENGTH_SHORT).show(); return; } } // 添加到当前订单的产品列表 Dingdan_Chanpin dc = new Dingdan_Chanpin(); dc.setId(selectedDingdan.getChanpins().size() + 1); dc.setChanpin(chanpin); dc.setDingdan(selectedDingdan); selectedDingdan.getChanpins().add(dc); // 刷新产品下拉框 setupChanpinSpinner(selectedDingdan); // 选中新添加的产品 spinnerChanpin.setSelection(selectedDingdan.getChanpins().size() - 1); Toast.makeText(getContext(), "产品添加成功", Toast.LENGTH_SHORT).show(); } // 为当前产品添加组件 private void addZujianToChanpin() { if (selectedChanpin == null) { Toast.makeText(getContext(), "请先选择产品", Toast.LENGTH_SHORT).show(); return; } // // 创建新组件(示例) // Zujian newZujian = new Zujian(); // newZujian.setId( (Data.zujians.size() + 1)); // newZujian.setName("新组件" + System.currentTimeMillis()); // // // 添加到全局列表 // Data.zujians.add(newZujian); // // // 添加到当前产品的组件列表 // Chanpin_Zujian cz = new Chanpin_Zujian(); // cz.setId(selectedChanpin.getZujians().size() + 1); // cz.setZujian(newZujian); // cz.setChanpin(selectedChanpin); // selectedChanpin.getZujians().add(cz); // // // 刷新组件下拉框 // setupZujianSpinner(selectedChanpin); // spinnerZujian.setSelection(selectedChanpin.getZujians().size() - 1); // // Toast.makeText(getContext(), "组件添加成功", Toast.LENGTH_SHORT).show(); showCreateZujianDialog(); } // 新建订单对话框 /*** * 新建订单对话框 */ 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); // 设置今日日期作为默认值 Date today = new Date(); etOrderDate.setText(dateFormat.format(today)); // 日期选择监听器 DatePickerDialog.OnDateSetListener orderDateListener = (view, year, month, dayOfMonth) -> { Calendar cal = Calendar.getInstance(); cal.set(year, month, dayOfMonth); etOrderDate.setText(dateFormat.format(cal.getTime())); }; DatePickerDialog.OnDateSetListener deliveryDateListener = (view, year, month, dayOfMonth) -> { Calendar cal = Calendar.getInstance(); cal.set(year, month, dayOfMonth); etDeliveryDate.setText(dateFormat.format(cal.getTime())); }; // 下单日期选择按钮 btnPickOrderDate.setOnClickListener(v -> { Calendar cal = Calendar.getInstance(); new DatePickerDialog(requireContext(), orderDateListener, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH)) .show(); }); /** * / 出货日期选择按钮 */ btnPickDeliveryDate.setOnClickListener(v -> { Calendar cal = Calendar.getInstance(); new DatePickerDialog(requireContext(), deliveryDateListener, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH)) .show(); }); builder.setView(dialogView); builder.setPositiveButton("创建", (dialog, which) -> { String orderNumber = etOrderNumber.getText().toString().trim(); String orderDateStr = etOrderDate.getText().toString(); String deliveryDateStr = etDeliveryDate.getText().toString(); for (Dingdan dingdan:Data.dingdans ) { if(dingdan.getNumber().equals(orderNumber)){ Toast.makeText(getContext(), "已有该订单号", Toast.LENGTH_SHORT).show(); return; } } // 验证输入 if (orderNumber.isEmpty()) { Toast.makeText(getContext(), "请输入订单号", Toast.LENGTH_SHORT).show(); return; } try { // 解析日期 Date orderDate = dateFormat.parse(orderDateStr); Date deliveryDate = deliveryDateStr.isEmpty() ? null : dateFormat.parse(deliveryDateStr); // 创建订单 createAndSaveDingdan(orderNumber, orderDate, deliveryDate); } catch (ParseException e) { Toast.makeText(getContext(), "日期格式错误", Toast.LENGTH_SHORT).show(); } }); builder.setNegativeButton("取消", null); builder.show(); } /** * 创建并保存订单 */ private void createAndSaveDingdan(String orderNumber, Date orderDate, Date deliveryDate) { Dingdan newDingdan = new Dingdan(); newDingdan.setId(Data.dingdans.size() + 1); newDingdan.setNumber(orderNumber); newDingdan.setXiadan(orderDate); newDingdan.setJiaohuo(deliveryDate); newDingdan.setChanpins(new ArrayList<>()); Data.dingdans.add(newDingdan); // 刷新下拉框 setupDingdanSpinner(); spinnerDingdan.setSelection(Data.dingdans.size() - 1); Toast.makeText(getContext(), "新建订单成功", Toast.LENGTH_SHORT).show(); } /** * 显示添加产品弹窗 */ private void showAddChanpinDialog() { 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); Button btnNewChanpin = dialogView.findViewById(R.id.btn_new_chanpin); // 设置产品下拉框 Adapter.setupChanpinSpinner(spinnerChanpinSelection, Data.chanpins, getContext()); // 新建产品按钮点击事件 btnNewChanpin.setOnClickListener(v -> { showNewChanpinDialog(() -> { // 新建产品后刷新下拉框 Adapter.setupChanpinSpinner(spinnerChanpinSelection, Data.chanpins, getContext()); // 默认选中新建的产品 spinnerChanpinSelection.setSelection(Data.chanpins.size() - 1); }); }); builder.setView(dialogView); builder.setPositiveButton("添加", (dialog, which) -> { Chanpin selectedChanpin = (Chanpin) spinnerChanpinSelection.getSelectedItem(); if (selectedChanpin != null) { // 将选中的产品添加到当前订单 addChanpinToDingdan(selectedChanpin); } }); builder.setNegativeButton("取消", null); builder.show(); } /** * 显示新建产品弹窗 * @param refreshCallback 新建后的回调,用于刷新产品列表 */ private void showNewChanpinDialog(Runnable refreshCallback) { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("新建产品"); View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_new_chanpin, null); EditText etChanpinName = dialogView.findViewById(R.id.et_chanpin_name); builder.setView(dialogView); builder.setPositiveButton("创建", (dialog, which) -> { String chanpinName = etChanpinName.getText().toString().trim(); if (chanpinName.isEmpty()) { Toast.makeText(getContext(), "请输入产品名称", Toast.LENGTH_SHORT).show(); return; } // 检查名称是否重复 for (Chanpin cp : Data.chanpins) { if (cp.getName().equals(chanpinName)) { Toast.makeText(getContext(), "产品名称重复", Toast.LENGTH_SHORT).show(); return; } } // 创建新产品 Chanpin newChanpin = new Chanpin(); newChanpin.setId(Data.chanpins.size() + 1); newChanpin.setName(chanpinName); newChanpin.setZujians(new ArrayList<>()); Data.chanpins.add(newChanpin); refreshCallback.run(); Toast.makeText(getContext(), "产品创建成功", Toast.LENGTH_SHORT).show(); }); builder.setNegativeButton("取消", null); builder.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); EditText etZujianName = dialogView.findViewById(R.id.et_zujian_name); Spinner spinnerbancai = dialogView.findViewById(R.id.spinner_bancai); SearchView searchBancai = dialogView.findViewById(R.id.search_bancai); Button btnAddBancai = dialogView.findViewById(R.id.btn_add_bancai); // 设置添加板材按钮点击事件 btnAddBancai.setOnClickListener(v -> { // 弹出添加板材的弹窗,并传入当前Spinner用于刷新 showCreateBancaiDialog(spinnerbancai); }); // 板材适配器 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> filteredList = new ArrayList<>(); for (Bancai bancai : Data.bancais) { if ( bancai.TableText().toLowerCase().contains(newText.toLowerCase())) { filteredList.add(bancai); } } // 板材适配器 Adapter.setupBancaiSpinners(spinnerbancai,filteredList,getContext()); return true; } }); // 添加木皮预览标签 builder.setView(dialogView); builder.setPositiveButton("创建", (dialog, which) -> { // 获取用户输入 String zujianName = etZujianName.getText().toString().trim(); Bancai selectedBancai = (Bancai) spinnerbancai.getSelectedItem(); if (zujianName.isEmpty()) { Toast.makeText(getContext(), "请输入组件名称", Toast.LENGTH_SHORT).show(); return; } // 创建新组件 Zujian newZujian = new Zujian(); newZujian.setId(Data.zujians.size() + 1); newZujian.setName(zujianName); // 创建新板材 // 添加到全局列表 Data.zujians.add(newZujian); // 添加到当前产品的组件列表 Chanpin_Zujian cz = new Chanpin_Zujian(); cz.setId(selectedChanpin.getZujians().size() + 1); cz.setZujian(newZujian); cz.setBancai(selectedBancai); // 关联新创建的板材 cz.setChanpin(selectedChanpin); selectedChanpin.getZujians().add(cz); // 刷新组件下拉框 setupZujianSpinner(selectedChanpin); spinnerZujian.setSelection(selectedChanpin.getZujians().size() - 1); Toast.makeText(getContext(), "组件和板材添加成功", Toast.LENGTH_SHORT).show(); }); builder.setNegativeButton("取消", null); builder.show(); } // 显示创建板材的弹窗 private void showCreateBancaiDialog(Spinner spinnerToRefresh) { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("添加新板材"); // 加载布局 View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_create_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); EditText TextInputEditTextHoudu=dialogView.findViewById(R.id.edittext_houdu); TextInputEditTextHoudu.setTextIsSelectable(true); // 绑定新建材质按钮 Button btnNewCaizhi = dialogView.findViewById(R.id.btn_new_caizhi); btnNewCaizhi.setOnClickListener(v -> { showNewOptionDialog("材质", option -> { // 避免重复添加 for (Caizhi caizhi : Data.caizhis) { if (caizhi.getName().equals(option)) return; } // 创建新材质 Caizhi newCaizhi = new Caizhi(); newCaizhi.setName(option); newCaizhi.setId(Data.caizhis.size() + 1); newCaizhi.setBancais(new ArrayList<>()); Data.caizhis.add(newCaizhi); // 刷新下拉框 Adapter.setupCaizhiSpinner(spinnerCaizhi, Data.caizhis, requireContext()); spinnerCaizhi.setSelection(Data.caizhis.size() - 1); }); }); // 绑定新建木皮按钮 Button btnNewMupi = dialogView.findViewById(R.id.btn_new_mupi); btnNewMupi.setOnClickListener(v -> { // 弹出新建木皮对话框 showNewMupiDialog(() -> { // 回调中刷新木皮下拉框 Adapter.setupMupiSpinner(spinnerMupi1, Data.mupis, requireContext()); Adapter.setupMupiSpinner(spinnerMupi2, Data.mupis, requireContext()); }); }); // 获取所有材质选项(从现有板材中提取) List<Caizhi> allCaizhi = Data.caizhis; List<Mupi> allMupi = Data.mupis; // 设置下拉框适配器 Adapter.setupCaizhiSpinner(spinnerCaizhi, allCaizhi, requireContext()); Adapter.setupMupiSpinner(spinnerMupi1, allMupi, requireContext()); Adapter.setupMupiSpinner(spinnerMupi2, allMupi, requireContext()); builder.setView(dialogView); builder.setPositiveButton("创建", (dialog, which) -> { Caizhi caizhi = (Caizhi)spinnerCaizhi.getSelectedItem() ; Mupi mupi1 = (Mupi)spinnerMupi1.getSelectedItem() ; Mupi mupi2 = (Mupi) spinnerMupi2.getSelectedItem() ; // 获取 TextInputEditText 的内容并进行校验 String houduText = TextInputEditTextHoudu.getText().toString().trim(); Double houdu = null; try { if (!houduText.isEmpty()) { // 检查输入是否为空 houdu = Double.valueOf(houduText); // 尝试将字符串转换为 Double } } catch (NumberFormatException e) { // 捕获转换异常并提示用户 Toast.makeText(getContext(), "厚度输入无效,请输入数字", Toast.LENGTH_SHORT).show(); return; } // 校验 caizhi 和 houdu 是否均有效 if (caizhi == null || houdu == null) { Toast.makeText(getContext(), "请选择材质并输入有效的厚度", Toast.LENGTH_SHORT).show(); return; } // 创建新板材 Bancai newBancai = new Bancai(); newBancai.setId(Data.bancais.size() + 1); newBancai.setCaizhi(caizhi); newBancai.setMupi1(mupi1); newBancai.setMupi2(mupi2); newBancai.setHoudu(houdu); caizhi.getBancais().add(newBancai); if (mupi1 != null) { mupi1.getBancais().add(newBancai); } if (mupi2 != null) { mupi2.getBancais().add(newBancai); } // 添加到全局列表 Data.bancais.add(newBancai); // 刷新Spinner(如果传入) if (spinnerToRefresh != null) { Adapter.setupBancaiSpinners(spinnerToRefresh, Data.bancais, getContext()); spinnerToRefresh.setSelection(Data.bancais.size() - 1); } Toast.makeText(getContext(), "板材添加成功", Toast.LENGTH_SHORT).show(); }); builder.setNegativeButton("取消", null); builder.show(); } // 显示新建选项的弹窗 /** * 显示新建选项的弹窗 * @param type 新建什么 * @param listener 反回 */ private void showNewOptionDialog(String type, OnOptionCreatedListener listener) { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("新建" + type); final EditText input = new EditText(requireContext()); input.setHint("请输入" + type); builder.setView(input); builder.setPositiveButton("确定", (dialog, which) -> { String option = input.getText().toString().trim(); if (!option.isEmpty()) { listener.onOptionCreated(option); } }); builder.setNegativeButton("取消", null); builder.show(); } // 回调接口 interface OnOptionCreatedListener { void onOptionCreated(String option); } // 新建木皮对话框 private void showNewMupiDialog(Runnable refreshCallback) { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle("新建木皮"); View view = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_new_mupi, null); EditText etName = view.findViewById(R.id.et_mupi_name); RadioGroup rgFinish = view.findViewById(R.id.rg_finish); builder.setView(view); builder.setPositiveButton("创建", (dialog, which) -> { String name = etName.getText().toString().trim(); if (name.isEmpty()) { Toast.makeText(getContext(), "请输入木皮名称", Toast.LENGTH_SHORT).show(); return; } // 避免重复添加 for (Mupi m : Data.mupis) { if (m.getName().equals(name)) return; } // 创建木皮对象 Mupi newMupi = new Mupi(); newMupi.setId(Data.mupis.size() + 1); newMupi.setName(name); newMupi.setYou(rgFinish.getCheckedRadioButtonId() == R.id.rb_painted); newMupi.setBancais(new ArrayList<>()); Data.mupis.add(newMupi); refreshCallback.run(); }); builder.setNegativeButton("取消", null); builder.show(); } } E FATAL EXCEPTION: main Process: com.example.kucun2, PID: 22195 java.lang.IllegalArgumentException: com.example.kucun2.entity.data.SynchronizableEntity is not an interface at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:635) at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:602) at java.lang.reflect.WeakCache$Factory.get(WeakCache.java:230) at java.lang.reflect.WeakCache.get(WeakCache.java:127) at java.lang.reflect.Proxy.getProxyClass0(Proxy.java:438) at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:873) at com.example.kucun2.entity.data.SynchronizedList.createProxy(SynchronizedList.java:186) at com.example.kucun2.entity.data.SynchronizedList.add(SynchronizedList.java:263) at com.example.kucun2.ui.jinhuo.AddInventoryFragment.createAndSaveDingdan(AddInventoryFragment.java:445) at com.example.kucun2.ui.jinhuo.AddInventoryFragment.lambda$showNewDingdanDialog$8(AddInventoryFragment.java:423) at com.example.kucun2.ui.jinhuo.AddInventoryFragment.$r8$lambda$viLBw5kNmkDSVG17JoXzuH5G85E(Unknown Source:0) at com.example.kucun2.ui.jinhuo.AddInventoryFragment$$ExternalSyntheticLambda20.onClick(D8$$SyntheticClass:0) at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:250) at android.os.Handler.dispatchMessage(Handler.java:109) at android.os.Looper.loopOnce(Looper.java:250) at android.os.Looper.loop(Looper.java:340) at android.app.ActivityThread.main(ActivityThread.java:9913) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:621) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:957) 2025-06-09 20:52:42.415 22195-22195 Process com.example.kucun2 I Sending signal. PID: 22195 SIG: 9 2025-06-09 21:35:57.386 22849-22849 AndroidRuntime com.example.kucun2 E FATAL EXCEPTION: main Process: com.example.kucun2, PID: 22849 java.lang.ClassCastException: $Proxy4 cannot be cast to com.example.kucun2.entity.data.SynchronizableEntity at com.example.kucun2.entity.data.SynchronizedList.createProxy(SynchronizedList.java:188) at com.example.kucun2.entity.data.SynchronizedList.add(SynchronizedList.java:265) at com.example.kucun2.ui.jinhuo.AddInventoryFragment.createAndSaveDingdan(AddInventoryFragment.java:445) at com.example.kucun2.ui.jinhuo.AddInventoryFragment.lambda$showNewDingdanDialog$8(AddInventoryFragment.java:423) at com.example.kucun2.ui.jinhuo.AddInventoryFragment.$r8$lambda$viLBw5kNmkDSVG17JoXzuH5G85E(Unknown Source:0) at com.example.kucun2.ui.jinhuo.AddInventoryFragment$$ExternalSyntheticLambda20.onClick(D8$$SyntheticClass:0) at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:250) at android.os.Handler.dispatchMessage(Handler.java:109) at android.os.Looper.loopOnce(Looper.java:250) at android.os.Looper.loop(Looper.java:340) at android.app.ActivityThread.main(ActivityThread.java:9913) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:621) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:957)
06-10
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.User; import com.example.kucun2.function.MyAppFunction; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import okhttp3.*; import java.io.IOException; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Map; /** * 重构版API客户端 - 更灵活的类型处理 * 主要改进: * 1. 分离请求参数类型和响应类型 * 2. 支持多种请求方法(GET/POST/PUT/DELETE) * 3. 支持表单和JSON两种请求格式 * 4. 自动推导响应类型 * 5. 统一的请求执行流程 */ public class ApiClient { private static final Gson gson = GsonFactory.createGson(); private static final String TAG = "ApiClient"; private static final MediaType JSON = MediaType.get("application/json; charset=utf-8"); private static final int MAX_RETRY = 3; private static final Handler MAIN_HANDLER = new Handler(Looper.getMainLooper()); // ====================== 核心请求方法 ====================== /** * 执行API请求(核心方法) * @param request 构建好的OkHttp请求 * @param responseType 期望的响应类型 * @param callback 回调接口 * @param <R> 响应数据类型 */ public static <R> void executeRequest(Request request, Type responseType, ApiCallback<R> callback) { OkHttpClient client = MyAppFunction.getClient(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { handleFailure(call, e, callback, 0); } @Override public void onResponse(Call call, Response response) throws IOException { handleResponse(response, responseType, callback); } }); } // ====================== 请求构建方法 ====================== /** * 构建JSON请求 * @param url API地址 * @param method 请求方法("POST", "PUT", "DELETE") * @param requestData 请求数据对象 * @return 构建好的Request对象 */ public static Request buildJsonRequest(String url, String method, Object requestData) { String jsonRequest = ReflectionJsonUtils.toJson(requestData); Log.d(TAG, method + " URL: " + url); Log.d(TAG, "请求数据: " + jsonRequest); RequestBody body = RequestBody.create(JSON, jsonRequest); return new Request.Builder() .url(url) .method(method, body) .build(); } /** * 构建表单请求 * @param url API地址 * @param method 请求方法 * @param formData 表单数据 * @return 构建好的Request对象 */ public static Request buildFormRequest(String url, String method, Map<String, String> formData) { FormBody.Builder builder = new FormBody.Builder(); for (Map.Entry<String, String> entry : formData.entrySet()) { builder.add(entry.getKey(), entry.getValue()); } Log.d(TAG, method + " URL: " + url); Log.d(TAG, "表单数据: " + formData); return new Request.Builder() .url(url) .method(method, builder.build()) .build(); } // ====================== 响应处理方法 ====================== private static <R> void handleResponse(Response response, Type responseType, ApiCallback<R> callback) throws IOException { try (ResponseBody responseBody = response.body()) { if (!response.isSuccessful()) { String error = "HTTP " + response.code() + ": " + response.message(); Log.e(TAG, error); notifyError(callback, response.code(), error); return; } String jsonResponse = responseBody.string(); Log.d(TAG, "服务器响应: " + jsonResponse); // 解析服务端的Information包装 Information<R> wrapper = gson.fromJson(jsonResponse, responseType); if (wrapper != null && wrapper.getStatus() == 200) { notifySuccess(callback, wrapper.getData()); } else { String errorMsg = wrapper != null ? "服务端错误: " + wrapper.getStatus() + " - " + wrapper.getText() : "无效的响应格式"; Log.e(TAG, errorMsg); notifyError(callback, wrapper != null ? wrapper.getStatus() : -1, errorMsg); } } catch (Exception e) { Log.e(TAG, "响应处理异常: " + e.getMessage()); notifyError(callback, -2, "数据处理异常: " + e.getMessage()); } } // ====================== 失败处理与重试 ====================== private static <R> void handleFailure(Call call, IOException e, ApiCallback<R> callback, int retryCount) { if (retryCount < MAX_RETRY) { Log.w(TAG, "请求失败,第" + (retryCount + 1) + "次重试: " + e.getMessage()); MAIN_HANDLER.postDelayed(() -> { call.clone().enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { handleFailure(call, e, callback, retryCount + 1); } @Override public void onResponse(Call call, Response response) throws IOException { handleResponse(response, getResponseType(callback), callback); } }); }, 2000); } else { Log.e(TAG, "最终请求失败: " + e.getMessage()); notifyError(callback, -1, "网络请求失败: " + e.getMessage()); } } // ====================== 类型处理工具 ====================== /** * 获取响应类型(通过回调接口的泛型参数) */ private static <R> Type getResponseType(ApiCallback<R> callback) { if (callback == null) { return new TypeToken<Information<Object>>(){}.getType(); } // 尝试获取泛型类型 Type[] genericInterfaces = callback.getClass().getGenericInterfaces(); for (Type type : genericInterfaces) { if (type instanceof ParameterizedType) { ParameterizedType pType = (ParameterizedType) type; if (pType.getRawType().equals(ApiCallback.class)) { Type dataType = pType.getActualTypeArguments()[0]; return TypeToken.getParameterized(Information.class, dataType).getType(); } } } // 默认返回Object类型 Log.w(TAG, "无法确定响应类型,使用默认Object类型"); return new TypeToken<Information<Object>>(){}.getType(); } // ====================== 回调通知方法 ====================== private static <R> void notifySuccess(ApiCallback<R> callback, R data) { if (callback != null) { MAIN_HANDLER.post(() -> callback.onSuccess(data)); } } private static <R> void notifyError(ApiCallback<R> callback, int code, String error) { if (callback != null) { MAIN_HANDLER.post(() -> callback.onError(code, error)); } } // ====================== 专用API方法 ====================== /** * 执行JSON API请求 * @param url API地址 * @param method 请求方法 * @param requestData 请求数据 * @param callback 回调接口 * @param <T> 请求数据类型 * @param <R> 响应数据类型 */ public static <T, R> void jsonRequest(String url, String method, T requestData, ApiCallback<R> callback) { Request request = buildJsonRequest(url, method, requestData); executeRequest(request, getResponseType(callback), callback); } /** * 执行表单API请求 * @param url API地址 * @param method 请求方法 * @param formData 表单数据 * @param callback 回调接口 * @param <R> 响应数据类型 */ public static <R> void formRequest(String url, String method, Map<String, String> formData, ApiCallback<R> callback) { Request request = buildFormRequest(url, method, formData); executeRequest(request, getResponseType(callback), callback); } // ====================== 便捷方法 ====================== public static <T, R> void postJson(String url, T data, ApiCallback<R> callback) { jsonRequest(url, "POST", data, callback); } public static <T, R> void putJson(String url, T data, ApiCallback<R> callback) { jsonRequest(url, "PUT", data, callback); } public static <T, R> void deleteJson(String url, T data, ApiCallback<R> callback) { jsonRequest(url, "DELETE", data, callback); } public static <R> void get(String url, ApiCallback<R> callback) { Request request = new Request.Builder().url(url).get().build(); executeRequest(request, getResponseType(callback), callback); } // ====================== 登录专用方法 ====================== public static void login(String username, String password, LoginCallback callback) { String url = MyAppFunction.getApiUrl("url_login"); Log.d(TAG, "login: " + url); formRequest(url, "POST", Map.of( "andy", username, "pass", password ), new ApiCallback<User>() { @Override public void onSuccess(User user) { if (callback != null) callback.onSuccess(user); } @Override public void onError(int statusCode, String error) { if (callback != null) callback.onFailure(error); } }); } // ====================== 回调接口定义 ====================== public interface ApiCallback<T> { void onSuccess(T data); void onError(int statusCode, String error); } public interface LoginCallback { void onSuccess(User user); void onFailure(String error); } } package com.example.kucun2.entity.data; import android.util.Log; import com.example.kucun2.function.MyAppFunction; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 可同步实体基类 * 提供实体到服务端的同步功能,包含自动重试机制和线程管理 */ public abstract class SynchronizableEntity implements EntityClassGrassrootsid { private static final String TAG = "SynchronizableEntity"; // 双重缓存结构:外层缓存类名,内层缓存字段名->Field对象 private static final Map<Class<?>, Map<String, Field>> CLASS_FIELD_CACHE = new HashMap<>(); // 网络请求线程池(静态共享) private static final ExecutorService NETWORK_EXECUTOR = Executors.newFixedThreadPool(4); /** * 获取指定类型操作的端点URL * * @param type 操作类型(如"create", "update", "delete"等) * @return 完整的端点URL路径 * * @apiNote 该方法通过资源键名拼接规则查找对应的URL资源 * @example 对于Product类的create操作,查找键为:"url_create_product" */ public String getEndpoint(String type) { // 构建资源键名:url_操作类型_类名小写 String key = "url_" + type + "_" + this.getClass().getSimpleName().toLowerCase(); return MyAppFunction.getApiUrl(key); } //================ 核心同步方法 ================// /** * 同步实体到服务端(公开接口) * * @param type 操作类型(如"add", "update","select","detect","all"等) * @param callback 同步结果回调接口 * * @implNote 内部调用私有方法实现带重试机制的同步 * @see #sync(String, SyncCallback, int) */ public void sync(String type, SyncCallback callback) { sync(type, callback, 0); // 初始重试次数为0 } private <T extends SynchronizableEntity> ApiClient.ApiCallback<T> getApiCallback(String type,SyncCallback callback,int retryCount,T thistype){ return new ApiClient.ApiCallback<T>() { @Override public void onSuccess(T responseData) { handleSyncSuccess(responseData, callback); } @Override public void onError(int statusCode, String error) { Log.d(TAG, "onError: "+thistype); handleSyncError(type, statusCode, error, callback, retryCount); } }; } private <T extends SynchronizableEntity> ApiClient.ApiCallback<T> getApiCallbackList(String type,SyncCallback callback,int retryCount,T thistype){ return new ApiClient.ApiCallback<T>() { @Override public void onSuccess(T responseData) { handleSyncSuccess(responseData, callback); } @Override public void onError(int statusCode, String error) { handleSyncError(type, statusCode, error, callback, retryCount); } }; } /** * 带重试机制的同步实现(私有方法) * * @param type 操作类型 * @param callback 同步结果回调 * @param retryCount 当前重试次数 * * @implSpec 1. 构建完整端点URL * 2. 通过线程池提交网络请求 * 3. 处理成功/失败回调 */ private void sync(String type, SyncCallback callback, int retryCount) { // 构建完整端点URL String endpoint =getEndpoint(type); Log.d(TAG, "同步端点: " + endpoint + ", 重试次数: " + retryCount); // 提交到线程池执行网络请求 NETWORK_EXECUTOR.execute(() -> { ApiClient.postJson(endpoint, this, getApiCallback(type,callback,retryCount,this)); }); } /** * 处理同步成功结果 * * @param responseData 服务端返回的实体数据 * @param callback 同步结果回调 * * @implNote 1. 更新实体ID * 2. 记录成功日志 * 3. 触发成功回调 */ private void handleSyncSuccess(SynchronizableEntity responseData, SyncCallback callback) { // 更新实体ID(如果服务端返回了新ID) if (responseData != null) { setId(responseData.getId()); Log.i(TAG, "同步成功, 新ID: " + responseData.getId()); } // 触发成功回调 if (callback != null) callback.onSyncSuccess(this); } /** * 处理同步错误(含重试逻辑) * * @param type 操作类型 * @param statusCode HTTP状态码(-1表示网络错误) * @param error 错误信息 * @param callback 同步结果回调 * @param retryCount 当前重试次数 * * @implSpec 1. 判断错误是否可重试(网络错误或5xx服务错误) * 2. 满足条件时进行指数退避重试 * 3. 达到最大重试次数后触发失败回调 * * @algorithm 使用指数退避算法:延迟时间 = 1000ms * 2^重试次数 */ private void handleSyncError(String type, int statusCode, String error, SyncCallback callback, int retryCount) { Log.e(TAG, "同步失败: " + error + ", 状态码: " + statusCode); // 判断是否可重试(网络错误或服务端5xx错误) boolean canRetry = statusCode == -1 || (statusCode >= 500 && statusCode < 600); // 满足重试条件(可重试错误且未达到最大重试次数) if (canRetry && retryCount < 3) { // 计算指数退避延迟时间 long delay = (long) (1000 * Math.pow(2, retryCount)); Log.w(TAG, "将在 " + delay + "ms 后重试"); try { // 当前线程休眠指定时间 Thread.sleep(delay); } catch (InterruptedException e) { // 恢复中断状态 Thread.currentThread().interrupt(); } // 递归调用进行重试(重试次数+1) sync(type, callback, retryCount + 1); } else { // 不可重试或达到最大重试次数,触发失败回调 if (callback != null) { String finalError = "同步失败: " + error; if (canRetry) finalError += " (重试失败)"; callback.onSyncFailure(finalError); } } } // 线程安全的对象复制方法 public void updateFrom(Object source) { if ( source == null) return; Class<?> targetClass = this.getClass(); Class<?> sourceClass = source.getClass(); // 获取或创建字段缓存 Map<String, Field> targetFields = getOrCreateFieldCache(targetClass); Map<String, Field> sourceFields = getOrCreateFieldCache(sourceClass); // 遍历源对象字段 for (Map.Entry<String, Field> entry : sourceFields.entrySet()) { String fieldName = entry.getKey(); Field sourceField = entry.getValue(); // 查找目标对象对应字段 Field targetField = targetFields.get(fieldName); if (targetField != null) { // 类型兼容性检查 if (isCompatibleTypes(sourceField.getType(), targetField.getType())) { try { // 复制字段值 Object value = sourceField.get(source); targetField.set(this, value); } catch (IllegalAccessException e) { // 处理异常,记录日志 } } } } } // 获取或创建类的字段缓存 private static Map<String, Field> getOrCreateFieldCache(Class<?> clazz) { // 双重检查锁确保线程安全 if (!CLASS_FIELD_CACHE.containsKey(clazz)) { synchronized (clazz) { if (!CLASS_FIELD_CACHE.containsKey(clazz)) { Map<String, Field> fieldMap = new HashMap<>(); // 递归获取所有字段(包括父类) for (Class<?> current = clazz; current != null; current = current.getSuperclass()) { for (Field field : current.getDeclaredFields()) { field.setAccessible(true); // 突破访问限制 fieldMap.put(field.getName(), field); } } CLASS_FIELD_CACHE.put(clazz, fieldMap); } } } return CLASS_FIELD_CACHE.get(clazz); } // 类型兼容性检查(支持自动装箱/拆箱) private static boolean isCompatibleTypes(Class<?> sourceType, Class<?> targetType) { // 处理基本类型和包装类的兼容性 if (sourceType.isPrimitive()) { sourceType = primitiveToWrapper(sourceType); } if (targetType.isPrimitive()) { targetType = primitiveToWrapper(targetType); } return targetType.isAssignableFrom(sourceType); } // 基本类型转包装类 private static Class<?> primitiveToWrapper(Class<?> primitiveType) { if (boolean.class.equals(primitiveType)) return Boolean.class; if (byte.class.equals(primitiveType)) return Byte.class; if (char.class.equals(primitiveType)) return Character.class; if (double.class.equals(primitiveType)) return Double.class; if (float.class.equals(primitiveType)) return Float.class; if (int.class.equals(primitiveType)) return Integer.class; if (long.class.equals(primitiveType)) return Long.class; if (short.class.equals(primitiveType)) return Short.class; if (void.class.equals(primitiveType)) return Void.class; return primitiveType; } //================ 回调接口 ================// /** * 同步操作回调接口 * * @implNote 使用方需实现此接口处理同步结果 */ public interface SyncCallback { /** * 同步成功回调 * * @param entity 同步后的实体对象(已更新ID) */ void onSyncSuccess(SynchronizableEntity entity); /** * 同步失败回调 * * @param error 失败原因描述 */ void onSyncFailure(String error); } } package com.example.kucun2.DataPreserver; import android.content.Context; import android.os.Handler; import android.os.Looper; import android.util.Log; import com.example.kucun2.entity.*; import com.example.kucun2.entity.Information; import com.example.kucun2.entity.data.*; import com.example.kucun2.function.MyAppFunction; import com.google.gson.reflect.TypeToken; import java.lang.reflect.Type; import java.util.List; /** * 重构后的数据加载器:使用ApiClient处理网络请求 */ public class DataLoader { private static final String TAG = "DataLoader"; private final DataStore dataStore; private final DataAssociator dataAssociator; // private final DataPreserver dataPreserver; public DataLoader(DataStore dataStore, DataAssociator dataAssociator ) { this.dataStore = dataStore; this.dataAssociator = dataAssociator; // this.dataPreserver = dataPreserver; } public void loadAllData(Context context, LoadDataCallback callback) { if (Looper.myLooper() != Looper.getMainLooper()) { throw new IllegalStateException("必须在主线程调用Data.loadAllData"); } // dataPreserver.ensurePreservedObjects(); String url = MyAppFunction.getApiUrl("url_all"); Log.d(TAG, "开始加载数据, URL: " + url); // 使用ApiClient的get方法发送请求 ApiClient.get(url, new ApiClient.ApiCallback<DataLoader.AllDataResponse>() { @Override public void onSuccess(AllDataResponse allData) { Log.d(TAG, "数据加载成功"); parseAndAssignData(allData, callback); } @Override public void onError(int statusCode, String error) { Log.e(TAG, "数据加载失败: " + error + ", 状态码: " + statusCode); new Handler(Looper.getMainLooper()).post(callback::onFailure); } }); } private void parseAndAssignData(AllDataResponse allData, LoadDataCallback callback) { try { mergeAllLists(allData); dataAssociator.automaticAssociation(); callback.onSuccess(); } catch (Exception e) { Log.e(TAG, "数据处理异常: " + e.getMessage()); callback.onFailure(); } } private void mergeAllLists(AllDataResponse allData) { mergeList(dataStore.bancais, allData.bancais); mergeList(dataStore.caizhis, allData.caizhis); mergeList(dataStore.mupis, allData.mupis); mergeList(dataStore.chanpins, allData.chanpins); mergeList(dataStore.chanpin_zujians, allData.chanpin_zujians); mergeList(dataStore.dingdans, allData.dingdans); mergeList(dataStore.dingdan_chanpins, allData.dingdan_chanpins); mergeList(dataStore.dingdan_bancais, allData.dingdan_bancais); mergeList(dataStore.kucuns, allData.kucuns); mergeList(dataStore.zujians, allData.zujians); mergeList(dataStore.users, allData.users); mergeList(dataStore.jinhuos, allData.jinhuos); } private <T extends SynchronizableEntity> void mergeList( SynchronizedList<T> targetList, List<T> newList) { if (newList == null) return; targetList.mergeList(newList); } public interface LoadDataCallback { void onSuccess(); void onFailure(); } public static class AllDataResponse { public List<Bancai> bancais; public List<Caizhi> caizhis; public List<Mupi> mupis; public List<Chanpin> chanpins; public List<Chanpin_Zujian> chanpin_zujians; public List<Dingdan> dingdans; public List<Dingdan_Chanpin> dingdan_chanpins; public List<Dingdan_bancai> dingdan_bancais; public List<Kucun> kucuns; public List<Zujian> zujians; public List<User> users; public List<Jinhuo> jinhuos; } } package com.example.kucun2.ui.login; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.example.kucun2.DataPreserver.Data; import com.example.kucun2.MainActivity; import com.example.kucun2.R; import com.example.kucun2.entity.User; import com.example.kucun2.entity.data.ApiClient; public class LoginActivity extends AppCompatActivity { private EditText etUsername, etPassword; private CheckBox cbRemember, cbAutoLogin; private Button btnLogin; private ProgressBar progressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_loading); // 初始化视图 etUsername = findViewById(R.id.et_username); etPassword = findViewById(R.id.et_password); cbRemember = findViewById(R.id.cb_remember); cbAutoLogin = findViewById(R.id.cb_auto_login); btnLogin = findViewById(R.id.btn_login); progressBar = findViewById(R.id.progress_bar); // 设置登录按钮点击事件 btnLogin.setOnClickListener(v -> attemptLogin()); } private void attemptLogin() { String username = etUsername.getText().toString().trim(); String password = etPassword.getText().toString().trim(); if (username.isEmpty() || password.isEmpty()) { Toast.makeText(this, "用户名或密码不能为空", Toast.LENGTH_SHORT).show(); return; } // 显示进度条,禁用登录按钮 progressBar.setVisibility(View.VISIBLE); btnLogin.setEnabled(false); // 调用网络登录 ApiClient.login(username, password, new ApiClient.LoginCallback() { @Override public void onSuccess(User user) { runOnUiThread(() -> { progressBar.setVisibility(View.GONE); btnLogin.setEnabled(true); // 保存登录状态 saveLoginPreferences(username, password); // 设置当前用户 Data.setCurrentUser(user); // 跳转到主界面 startMainActivity(); }); } @Override public void onFailure(String error) { runOnUiThread(() -> { progressBar.setVisibility(View.GONE); btnLogin.setEnabled(true); Toast.makeText(LoginActivity.this, "登录失败: " + error, Toast.LENGTH_SHORT).show(); }); } }); } private void saveLoginPreferences(String username, String password) { // 在实际应用中,应使用加密方式存储密码 getSharedPreferences("login_prefs", MODE_PRIVATE).edit() .putString("username", username) .putString("password", password) .putBoolean("remember", cbRemember.isChecked()) .putBoolean("auto_login", cbAutoLogin.isChecked()) .apply(); } private void startMainActivity() { Intent intent = new Intent(this, MainActivity.class); startActivity(intent); finish(); // 关闭登录界面 } } ------------------------登录和获取初始数据的时候一点问题没有,只有通过基类传递时出错了------------------------------------ java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.example.kucun2.entity.data.SynchronizableEntity at com.example.kucun2.entity.data.SynchronizableEntity$1.onSuccess(SynchronizableEntity.java:56)
最新发布
06-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值