20251003_042915_870
This commit is contained in:
		| @@ -1,8 +1,8 @@ | |||||||
| #Created by .winboll/winboll_app_build.gradle | #Created by .winboll/winboll_app_build.gradle | ||||||
| #Thu Oct 02 19:56:28 GMT 2025 | #Thu Oct 02 20:25:23 GMT 2025 | ||||||
| stageCount=8 | stageCount=8 | ||||||
| libraryProject= | libraryProject= | ||||||
| baseVersion=15.0 | baseVersion=15.0 | ||||||
| publishVersion=15.0.7 | publishVersion=15.0.7 | ||||||
| buildCount=51 | buildCount=52 | ||||||
| baseBetaVersion=15.0.8 | baseBetaVersion=15.0.8 | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ package cc.winboll.studio.positions.adapters; | |||||||
| /** | /** | ||||||
|  * @Author ZhanGSKen&豆包大模型<zhangsken@qq.com> |  * @Author ZhanGSKen&豆包大模型<zhangsken@qq.com> | ||||||
|  * @Date 2025/09/29 20:25 |  * @Date 2025/09/29 20:25 | ||||||
|  * @Describe 位置数据适配器(完全独立,无未知接口依赖,仅用LocationActivity缓存数据) |  * @Describe 位置数据适配器(集成PositionTaskListView,移除未定义onDestroy,Java 7语法适配) | ||||||
|  */ |  */ | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| import android.view.LayoutInflater; | import android.view.LayoutInflater; | ||||||
| @@ -15,6 +15,7 @@ import android.widget.EditText; | |||||||
| import android.widget.RadioGroup; | import android.widget.RadioGroup; | ||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
| import android.text.TextUtils; | import android.text.TextUtils; | ||||||
|  | import android.widget.Toast; | ||||||
| import androidx.recyclerview.widget.RecyclerView; | import androidx.recyclerview.widget.RecyclerView; | ||||||
|  |  | ||||||
| import cc.winboll.studio.libappbase.LogUtils; | import cc.winboll.studio.libappbase.LogUtils; | ||||||
| @@ -22,6 +23,7 @@ import cc.winboll.studio.positions.R; | |||||||
| import cc.winboll.studio.positions.models.PositionModel; | import cc.winboll.studio.positions.models.PositionModel; | ||||||
| import cc.winboll.studio.positions.models.PositionTaskModel; | import cc.winboll.studio.positions.models.PositionTaskModel; | ||||||
| import cc.winboll.studio.positions.services.MainService; | import cc.winboll.studio.positions.services.MainService; | ||||||
|  | import cc.winboll.studio.positions.views.PositionTaskListView; | ||||||
|  |  | ||||||
| import java.lang.ref.WeakReference; | import java.lang.ref.WeakReference; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| @@ -30,20 +32,20 @@ import java.util.Iterator; | |||||||
| import java.util.concurrent.ConcurrentHashMap; | import java.util.concurrent.ConcurrentHashMap; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Java 7 语法适配: |  * Java 7 语法严格适配: | ||||||
|  * 1. 移除 Lambda/方法引用,用匿名内部类替代 |  * 1. 无Lambda/方法引用,全匿名内部类实现回调 | ||||||
|  * 2. 集合操作使用迭代器(避免 ConcurrentModificationException) |  * 2. 移除未定义的 taskView.onDestroy(),改用「清空数据+解绑监听」替代资源释放 | ||||||
|  * 3. 弱引用管理 MainService,避免内存泄漏 |  * 3. 弱引用管理服务/控件,杜绝内存泄漏 | ||||||
|  * 4. 所有任务数据从 MainService 获取,更新通过 MainService 接口 |  * 4. PositionTaskListView 初始化/同步/资源释放全链路适配 | ||||||
|  */ |  */ | ||||||
| public class PositionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements MainService.TaskUpdateListener { | public class PositionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements MainService.TaskUpdateListener { | ||||||
|     public static final String TAG = "PositionAdapter"; |     public static final String TAG = "PositionAdapter"; | ||||||
|  |  | ||||||
|     // 视图类型常量(Java 7 静态常量定义) |     // 视图类型常量(静态常量统一管理) | ||||||
|     private static final int VIEW_TYPE_SIMPLE = 0; |     private static final int VIEW_TYPE_SIMPLE = 0; | ||||||
|     private static final int VIEW_TYPE_EDIT = 1; |     private static final int VIEW_TYPE_EDIT = 1; | ||||||
|  |  | ||||||
|     // 默认配置常量(统一管理,避免魔法值) |     // 默认配置常量(避免魔法值) | ||||||
|     private static final String DEFAULT_MEMO = "无备注"; |     private static final String DEFAULT_MEMO = "无备注"; | ||||||
|     private static final String DEFAULT_TASK_DESC = "新任务"; |     private static final String DEFAULT_TASK_DESC = "新任务"; | ||||||
|     private static final int DEFAULT_TASK_DISTANCE = 50; // 单位:米 |     private static final int DEFAULT_TASK_DISTANCE = 50; // 单位:米 | ||||||
| @@ -51,13 +53,17 @@ public class PositionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde | |||||||
|     private static final String DISTANCE_DISABLED = "实时距离:未启用"; |     private static final String DISTANCE_DISABLED = "实时距离:未启用"; | ||||||
|     private static final String DISTANCE_ERROR = "实时距离:计算失败"; |     private static final String DISTANCE_ERROR = "实时距离:计算失败"; | ||||||
|  |  | ||||||
|     // 核心依赖(Java 7 弱引用+集合定义) |     // 核心依赖(弱引用+线程安全集合,适配Java 7) | ||||||
|     private final Context mContext; |     private final Context mContext; | ||||||
|     private final ArrayList<PositionModel> mCachedPositionList; // 位置缓存(从Activity传入,最终需与MainService同步) |     private final ArrayList<PositionModel> mCachedPositionList; // 位置缓存(与MainService同步) | ||||||
|     private final WeakReference<MainService> mMainServiceRef;   // 弱引用MainService,避免内存泄漏 |     private final WeakReference<MainService> mMainServiceRef;   // 弱引用MainService,防内存泄漏 | ||||||
|     private final ConcurrentHashMap<String, TextView> mPosDistanceViewMap; // 距离控件缓存(优化UI更新) |     // 控件缓存:位置ID → 对应任务列表视图(分别缓存简单/编辑模式,避免引用混淆) | ||||||
|  |     private final ConcurrentHashMap<String, PositionTaskListView> mSimpleTaskViewMap; | ||||||
|  |     private final ConcurrentHashMap<String, PositionTaskListView> mEditTaskViewMap; | ||||||
|  |     // 距离控件缓存(用于局部更新距离UI) | ||||||
|  |     private final ConcurrentHashMap<String, TextView> mPosDistanceViewMap; | ||||||
|  |  | ||||||
|     // 回调接口(与Activity交互,仅处理位置逻辑,任务逻辑直接调用MainService) |     // 回调接口(仅处理位置逻辑,任务逻辑通过PositionTaskListView+MainService完成) | ||||||
|     public interface OnDeleteClickListener { |     public interface OnDeleteClickListener { | ||||||
|         void onDeleteClick(int position); |         void onDeleteClick(int position); | ||||||
|     } |     } | ||||||
| @@ -70,42 +76,42 @@ public class PositionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde | |||||||
|     private OnSavePositionClickListener mOnSavePosListener; |     private OnSavePositionClickListener mOnSavePosListener; | ||||||
|  |  | ||||||
|     // ========================================================================= |     // ========================================================================= | ||||||
|     // 构造函数(Java 7 风格:初始化依赖+注册任务监听) |     // 构造函数(初始化依赖+注册服务监听+初始化控件缓存) | ||||||
|     // ========================================================================= |     // ========================================================================= | ||||||
|     public PositionAdapter(Context context, ArrayList<PositionModel> cachedPositionList, MainService mainService) { |     public PositionAdapter(Context context, ArrayList<PositionModel> cachedPositionList, MainService mainService) { | ||||||
|         this.mContext = context; |         this.mContext = context; | ||||||
|         // 容错处理:避免传入null导致空指针 |         // 容错处理:避免传入null导致空指针 | ||||||
|         this.mCachedPositionList = (cachedPositionList != null) ? cachedPositionList : new ArrayList<PositionModel>(); |         this.mCachedPositionList = (cachedPositionList!= null)? cachedPositionList : new ArrayList<PositionModel>(); | ||||||
|         // 弱引用MainService:防止Adapter持有Service导致内存泄漏(Java 7 弱引用语法) |         // 弱引用MainService:防止Adapter持有服务导致内存泄漏(Java 7 弱引用语法) | ||||||
|         this.mMainServiceRef = new WeakReference<MainService>(mainService); |         this.mMainServiceRef = new WeakReference<MainService>(mainService); | ||||||
|         // 初始化距离控件缓存(线程安全集合,适配多线程更新场景) |         // 初始化控件缓存(线程安全集合,适配多线程更新场景) | ||||||
|  |         this.mSimpleTaskViewMap = new ConcurrentHashMap<String, PositionTaskListView>(); | ||||||
|  |         this.mEditTaskViewMap = new ConcurrentHashMap<String, PositionTaskListView>(); | ||||||
|         this.mPosDistanceViewMap = new ConcurrentHashMap<String, TextView>(); |         this.mPosDistanceViewMap = new ConcurrentHashMap<String, TextView>(); | ||||||
|  |  | ||||||
|         // 注册MainService任务监听:服务任务变化时自动刷新Adapter(Java 7 接口实现) |         // 注册MainService任务监听:服务任务变化时同步刷新任务列表视图 | ||||||
|         if (mainService != null) { |         if (mainService!= null) { | ||||||
|             mainService.registerTaskUpdateListener(this); |             mainService.registerTaskUpdateListener(this); | ||||||
|             LogUtils.d(TAG, "已注册MainService任务监听,确保任务数据与服务同步"); |             LogUtils.d(TAG, "已注册MainService任务监听,确保任务数据与服务同步"); | ||||||
|         } else { |         } else { | ||||||
|             LogUtils.w(TAG, "构造函数:MainService为空,任务数据无法同步"); |             LogUtils.w(TAG, "构造函数:MainService为空,PositionTaskListView无法初始化"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         LogUtils.d(TAG, "Adapter初始化完成:位置数量=" + mCachedPositionList.size()); |         LogUtils.d(TAG, "Adapter初始化完成:位置数量=" + mCachedPositionList.size()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // ========================================================================= |     // ========================================================================= | ||||||
|     // RecyclerView 核心方法(Java 7 语法适配) |     // RecyclerView 核心方法(视图类型判断+创建+绑定,集成任务列表视图) | ||||||
|     // ========================================================================= |     // ========================================================================= | ||||||
|     @Override |     @Override | ||||||
|     public int getItemViewType(int position) { |     public int getItemViewType(int position) { | ||||||
|         // 从位置缓存获取状态,判断视图类型(简单/编辑) |  | ||||||
|         PositionModel posModel = getPositionByIndex(position); |         PositionModel posModel = getPositionByIndex(position); | ||||||
|         return (posModel != null && posModel.isSimpleView()) ? VIEW_TYPE_SIMPLE : VIEW_TYPE_EDIT; |         return (posModel!= null && posModel.isSimpleView())? VIEW_TYPE_SIMPLE : VIEW_TYPE_EDIT; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { |     public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { | ||||||
|         LayoutInflater inflater = LayoutInflater.from(mContext); |         LayoutInflater inflater = LayoutInflater.from(mContext); | ||||||
|         // 根据视图类型加载对应布局(Java 7 条件判断) |  | ||||||
|         if (viewType == VIEW_TYPE_SIMPLE) { |         if (viewType == VIEW_TYPE_SIMPLE) { | ||||||
|             View simpleView = inflater.inflate(R.layout.item_position_simple, parent, false); |             View simpleView = inflater.inflate(R.layout.item_position_simple, parent, false); | ||||||
|             return new SimpleViewHolder(simpleView); |             return new SimpleViewHolder(simpleView); | ||||||
| @@ -122,65 +128,100 @@ public class PositionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde | |||||||
|             LogUtils.w(TAG, "onBindViewHolder:位置模型为空(索引=" + position + "),跳过绑定"); |             LogUtils.w(TAG, "onBindViewHolder:位置模型为空(索引=" + position + "),跳过绑定"); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         String posId = posModel.getPositionId(); |         final String posId = posModel.getPositionId(); | ||||||
|  |         MainService mainService = mMainServiceRef.get(); | ||||||
|  |  | ||||||
|         // 按视图类型绑定数据(Java 7 类型判断) |         // 按视图类型绑定数据(简单模式/编辑模式) | ||||||
|         if (holder instanceof SimpleViewHolder) { |         if (holder instanceof SimpleViewHolder) { | ||||||
|             bindSimpleView((SimpleViewHolder) holder, posModel); |             SimpleViewHolder simpleHolder = (SimpleViewHolder) holder; | ||||||
|         } else if (holder instanceof EditViewHolder) { |             // 1. 绑定位置基础数据(经纬度/备注/距离) | ||||||
|             bindEditView((EditViewHolder) holder, posModel, position); |             bindSimplePositionData(simpleHolder, posModel); | ||||||
|         } |             // 2. 初始化+绑定简单模式任务列表视图(仅显示已启用任务) | ||||||
|  |             initAndBindSimpleTaskView(simpleHolder.ptlvSimpleTasks, posId, mainService); | ||||||
|  |             // 3. 缓存简单模式任务视图+距离控件 | ||||||
|  |             mSimpleTaskViewMap.put(posId, simpleHolder.ptlvSimpleTasks); | ||||||
|  |             mPosDistanceViewMap.put(posId, simpleHolder.tvSimpleDistance); | ||||||
|  |  | ||||||
|         // 缓存当前位置的距离控件(后续局部更新距离时直接使用) |         } else if (holder instanceof EditViewHolder) { | ||||||
|         TextView distanceView = (holder instanceof SimpleViewHolder) |             EditViewHolder editHolder = (EditViewHolder) holder; | ||||||
| 			? ((SimpleViewHolder) holder).tvSimpleDistance |             // 1. 绑定位置基础数据(经纬度/备注/距离/距离开关) | ||||||
| 			: ((EditViewHolder) holder).tvEditDistance; |             bindEditPositionData(editHolder, posModel, position); | ||||||
|         if (distanceView != null && !TextUtils.isEmpty(posId)) { |             // 2. 初始化+绑定编辑模式任务列表视图(支持增删改查) | ||||||
|             mPosDistanceViewMap.put(posId, distanceView); |             initAndBindEditTaskView(editHolder.ptlvEditTasks, posId, mainService, editHolder.btnAddTask); | ||||||
|  |             // 3. 缓存编辑模式任务视图+距离控件 | ||||||
|  |             mEditTaskViewMap.put(posId, editHolder.ptlvEditTasks); | ||||||
|  |             mPosDistanceViewMap.put(posId, editHolder.tvEditDistance); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) { |     public void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) { | ||||||
|         super.onViewDetachedFromWindow(holder); |         super.onViewDetachedFromWindow(holder); | ||||||
|         // 视图离开屏幕时,移除距离控件缓存(避免内存泄漏+引用失效控件) |         // 视图离开屏幕时:清空对应控件缓存+释放任务列表视图资源(移除未定义的onDestroy()) | ||||||
|         PositionModel posModel = getPositionByIndex(holder.getAdapterPosition()); |         PositionModel posModel = getPositionByIndex(holder.getAdapterPosition()); | ||||||
|         if (posModel != null && !TextUtils.isEmpty(posModel.getPositionId())) { |         if (posModel == null || TextUtils.isEmpty(posModel.getPositionId())) { | ||||||
|             mPosDistanceViewMap.remove(posModel.getPositionId()); |             return; | ||||||
|             LogUtils.d(TAG, "视图脱离屏幕:移除位置ID=" + posModel.getPositionId() + "的距离控件缓存"); |         } | ||||||
|  |         String posId = posModel.getPositionId(); | ||||||
|  |  | ||||||
|  |         // 1. 移除距离控件缓存 | ||||||
|  |         if (mPosDistanceViewMap.containsKey(posId)) { | ||||||
|  |             mPosDistanceViewMap.remove(posId); | ||||||
|  |             LogUtils.d(TAG, "视图脱离屏幕:移除位置ID=" + posId + "的距离控件缓存"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 2. 释放简单模式任务视图资源(清空数据+解绑监听,替代onDestroy()) | ||||||
|  |         if (holder instanceof SimpleViewHolder && mSimpleTaskViewMap.containsKey(posId)) { | ||||||
|  |             PositionTaskListView taskView = mSimpleTaskViewMap.get(posId); | ||||||
|  |             if (taskView != null) { | ||||||
|  |                 taskView.clearData(); // 清空任务数据(假设视图已实现该方法,用于释放列表数据) | ||||||
|  |                 taskView.setOnTaskUpdatedListener(null); // 解绑任务更新监听,避免内存泄漏 | ||||||
|  |             } | ||||||
|  |             mSimpleTaskViewMap.remove(posId); | ||||||
|  |             LogUtils.d(TAG, "简单模式视图脱离屏幕:释放任务列表视图资源(位置ID=" + posId + ")"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 3. 释放编辑模式任务视图资源(清空数据+解绑监听,替代onDestroy()) | ||||||
|  |         if (holder instanceof EditViewHolder && mEditTaskViewMap.containsKey(posId)) { | ||||||
|  |             PositionTaskListView taskView = mEditTaskViewMap.get(posId); | ||||||
|  |             if (taskView != null) { | ||||||
|  |                 taskView.clearData(); // 清空任务数据 | ||||||
|  |                 taskView.setOnTaskUpdatedListener(null); // 解绑任务更新监听 | ||||||
|  |             } | ||||||
|  |             mEditTaskViewMap.remove(posId); | ||||||
|  |             LogUtils.d(TAG, "编辑模式视图脱离屏幕:释放任务列表视图资源(位置ID=" + posId + ")"); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public int getItemCount() { |     public int getItemCount() { | ||||||
|         // 直接从位置缓存获取数量(数据源唯一) |  | ||||||
|         return mCachedPositionList.size(); |         return mCachedPositionList.size(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // ========================================================================= |     // ========================================================================= | ||||||
|     // 视图绑定逻辑(Java 7 风格:任务数据从MainService获取) |     // 位置数据绑定(分简单/编辑模式,独立逻辑解耦) | ||||||
|     // ========================================================================= |     // ========================================================================= | ||||||
|     /** |     /** | ||||||
|      * 绑定简单视图(仅显示数据,点击切换到编辑视图) |      * 绑定简单模式位置数据(仅显示,无编辑操作) | ||||||
|      */ |      */ | ||||||
|     private void bindSimpleView(final SimpleViewHolder holder, final PositionModel posModel) { |     private void bindSimplePositionData(SimpleViewHolder holder, final PositionModel posModel) { | ||||||
|         // 1. 显示经纬度(Java 7 String.format格式化) |         // 1. 经纬度显示(保留6位小数,格式统一) | ||||||
|         holder.tvSimpleLon.setText(String.format("经度:%.6f", posModel.getLongitude())); |         holder.tvSimpleLon.setText(String.format("经度:%.6f", posModel.getLongitude())); | ||||||
|         holder.tvSimpleLat.setText(String.format("纬度:%.6f", posModel.getLatitude())); |         holder.tvSimpleLat.setText(String.format("纬度:%.6f", posModel.getLatitude())); | ||||||
|  |  | ||||||
|         // 2. 显示备注(无备注时显示默认文本) |         // 2. 备注显示(无备注时显示默认文本) | ||||||
|         String memo = posModel.getMemo(); |         String memo = posModel.getMemo(); | ||||||
|         holder.tvSimpleMemo.setText("备注:" + (TextUtils.isEmpty(memo) ? DEFAULT_MEMO : memo)); |         holder.tvSimpleMemo.setText("备注:" + (TextUtils.isEmpty(memo)? DEFAULT_MEMO : memo)); | ||||||
|  |  | ||||||
|         // 3. 显示实时距离(从位置模型取数,调用工具方法更新显示) |         // 3. 实时距离显示(按状态区分文本+颜色) | ||||||
|         updateDistanceDisplay(holder.tvSimpleDistance, posModel); |         updateDistanceDisplay(holder.tvSimpleDistance, posModel); | ||||||
|  |  | ||||||
|         // 4. 点击切换到编辑视图(Java 7 匿名内部类实现点击事件) |         // 4. 点击切换到编辑模式 | ||||||
|         holder.itemView.setOnClickListener(new View.OnClickListener() { |         holder.itemView.setOnClickListener(new View.OnClickListener() { | ||||||
| 				@Override | 				@Override | ||||||
| 				public void onClick(View v) { | 				public void onClick(View v) { | ||||||
| 					posModel.setIsSimpleView(false); // 修改位置缓存状态 | 					posModel.setIsSimpleView(false); | ||||||
| 					// 通知RecyclerView刷新当前项(精准更新,避免全量刷新) | 					// 精准刷新当前项(避免全量刷新) | ||||||
| 					notifyItemChanged(getPositionIndexById(posModel.getPositionId())); | 					notifyItemChanged(getPositionIndexById(posModel.getPositionId())); | ||||||
| 					LogUtils.d(TAG, "简单视图点击:位置ID=" + posModel.getPositionId() + ",切换到编辑视图"); | 					LogUtils.d(TAG, "简单视图点击:位置ID=" + posModel.getPositionId() + ",切换到编辑视图"); | ||||||
| 				} | 				} | ||||||
| @@ -188,151 +229,186 @@ public class PositionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 绑定编辑视图(支持修改备注、开关距离、删除/保存位置、新增任务) |      * 绑定编辑模式位置数据(支持备注修改/距离开关/删除/保存) | ||||||
|      */ |      */ | ||||||
|     private void bindEditView(final EditViewHolder holder, final PositionModel posModel, final int position) { |     private void bindEditPositionData(final EditViewHolder holder, final PositionModel posModel, final int position) { | ||||||
|         final String posId = posModel.getPositionId(); |         final String posId = posModel.getPositionId(); | ||||||
|  |  | ||||||
|         // 1. 显示经纬度(不可编辑,仅展示) |         // 1. 经纬度显示(不可编辑,仅展示) | ||||||
|         holder.tvEditLon.setText(String.format("经度:%.6f", posModel.getLongitude())); |         holder.tvEditLon.setText(String.format("经度:%.6f", posModel.getLongitude())); | ||||||
|         holder.tvEditLat.setText(String.format("纬度:%.6f", posModel.getLatitude())); |         holder.tvEditLat.setText(String.format("纬度:%.6f", posModel.getLatitude())); | ||||||
|  |  | ||||||
|         // 2. 显示备注(编辑框赋值,光标定位到末尾) |         // 2. 备注编辑(填充现有备注,光标定位到末尾) | ||||||
|         String memo = posModel.getMemo(); |         String memo = posModel.getMemo(); | ||||||
|         if (!TextUtils.isEmpty(memo)) { |         if (!TextUtils.isEmpty(memo)) { | ||||||
|             holder.etEditMemo.setText(memo); |             holder.etEditMemo.setText(memo); | ||||||
|             holder.etEditMemo.setSelection(memo.length()); // 光标定位到文本末尾 |             holder.etEditMemo.setSelection(memo.length()); | ||||||
|         } else { |         } else { | ||||||
|             holder.etEditMemo.setText(""); // 无备注时清空编辑框 |             holder.etEditMemo.setText(""); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 3. 显示实时距离(与简单视图逻辑一致) |         // 3. 实时距离显示(与简单模式逻辑一致) | ||||||
|         updateDistanceDisplay(holder.tvEditDistance, posModel); |         updateDistanceDisplay(holder.tvEditDistance, posModel); | ||||||
|  |  | ||||||
|         // 4. 设置距离开关状态(匹配位置缓存中的启用状态) |         // 4. 距离开关状态(匹配位置模型中的启用状态) | ||||||
|         holder.rgDistanceSwitch.check(posModel.isEnableRealPositionDistance() |         holder.rgDistanceSwitch.check(posModel.isEnableRealPositionDistance() | ||||||
| 									  ? R.id.rb_distance_enable | 									  ? R.id.rb_distance_enable | ||||||
| 									  : R.id.rb_distance_disable); | 									  : R.id.rb_distance_disable); | ||||||
|  |  | ||||||
|         // 5. 取消编辑:切换回简单视图(Java 7 匿名内部类) |         // 5. 取消编辑:切换回简单模式+隐藏软键盘 | ||||||
|         holder.btnCancel.setOnClickListener(new View.OnClickListener() { |         holder.btnCancel.setOnClickListener(new View.OnClickListener() { | ||||||
| 				@Override | 				@Override | ||||||
| 				public void onClick(View v) { | 				public void onClick(View v) { | ||||||
| 					posModel.setIsSimpleView(true); | 					posModel.setIsSimpleView(true); | ||||||
| 					notifyItemChanged(position); | 					notifyItemChanged(position); | ||||||
| 					hideSoftKeyboard(v); // 隐藏软键盘(提升用户体验) | 					hideSoftKeyboard(v); | ||||||
| 					LogUtils.d(TAG, "取消编辑:位置ID=" + posId + ",切换回简单视图"); | 					LogUtils.d(TAG, "取消编辑:位置ID=" + posId + ",切换回简单视图"); | ||||||
| 				} | 				} | ||||||
| 			}); | 			}); | ||||||
|  |  | ||||||
|         // 6. 删除位置:回调Activity处理(Adapter不直接删数据,由Activity同步MainService) |         // 6. 删除位置:回调Activity处理(Adapter不直接操作数据) | ||||||
|         holder.btnDelete.setOnClickListener(new View.OnClickListener() { |         holder.btnDelete.setOnClickListener(new View.OnClickListener() { | ||||||
| 				@Override | 				@Override | ||||||
| 				public void onClick(View v) { | 				public void onClick(View v) { | ||||||
| 					if (mOnDeleteListener != null) { | 					if (mOnDeleteListener != null) { | ||||||
| 						mOnDeleteListener.onDeleteClick(position); // 通知Activity删除指定索引 | 						mOnDeleteListener.onDeleteClick(position); | ||||||
| 					} | 					} | ||||||
| 					hideSoftKeyboard(v); | 					hideSoftKeyboard(v); | ||||||
| 					LogUtils.d(TAG, "触发删除:通知Activity处理位置ID=" + posId + "的删除逻辑"); | 					LogUtils.d(TAG, "触发删除:通知Activity处理位置ID=" + posId + "的删除逻辑"); | ||||||
| 				} | 				} | ||||||
| 			}); | 			}); | ||||||
|  |  | ||||||
|         // 7. 保存位置:回调Activity保存(收集参数→构建更新模型→通知Activity) |         // 7. 保存位置:收集参数→更新模型→回调Activity→切换视图 | ||||||
|         holder.btnSave.setOnClickListener(new View.OnClickListener() { |         holder.btnSave.setOnClickListener(new View.OnClickListener() { | ||||||
| 				@Override | 				@Override | ||||||
| 				public void onClick(View v) { | 				public void onClick(View v) { | ||||||
| 					// 收集编辑后的参数(备注+距离启用状态) | 					// 收集编辑后的数据 | ||||||
| 					String newMemo = holder.etEditMemo.getText().toString().trim(); | 					String newMemo = holder.etEditMemo.getText().toString().trim(); | ||||||
| 					boolean isDistanceEnable = (holder.rgDistanceSwitch.getCheckedRadioButtonId() == R.id.rb_distance_enable); | 					boolean isDistanceEnable = (holder.rgDistanceSwitch.getCheckedRadioButtonId() == R.id.rb_distance_enable); | ||||||
|  |  | ||||||
| 					// 构建更新后的位置模型(保留原核心数据,仅更新可编辑字段) | 					// 构建更新后的位置模型(保留核心不可编辑字段) | ||||||
| 					PositionModel updatedPos = new PositionModel(); | 					PositionModel updatedPos = new PositionModel(); | ||||||
| 					updatedPos.setPositionId(posId); // 保留原ID(不可修改) | 					updatedPos.setPositionId(posId); | ||||||
| 					updatedPos.setLongitude(posModel.getLongitude()); // 保留原经度(不可编辑) | 					updatedPos.setLongitude(posModel.getLongitude()); | ||||||
| 					updatedPos.setLatitude(posModel.getLatitude());   // 保留原纬度(不可编辑) | 					updatedPos.setLatitude(posModel.getLatitude()); | ||||||
| 					updatedPos.setMemo(newMemo);                      // 更新备注(用户编辑) | 					updatedPos.setMemo(newMemo); | ||||||
| 					updatedPos.setIsEnableRealPositionDistance(isDistanceEnable); // 更新距离状态 | 					updatedPos.setIsEnableRealPositionDistance(isDistanceEnable); | ||||||
| 					updatedPos.setIsSimpleView(true);                 // 切换回简单视图 | 					updatedPos.setIsSimpleView(true); | ||||||
|  |  | ||||||
| 					// 回调Activity保存(由Activity同步MainService+位置缓存,Adapter不处理逻辑) | 					// 回调Activity保存(由Activity同步MainService) | ||||||
| 					if (mOnSavePosListener != null) { | 					if (mOnSavePosListener != null) { | ||||||
| 						mOnSavePosListener.onSavePositionClick(position, updatedPos); | 						mOnSavePosListener.onSavePositionClick(position, updatedPos); | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 					// 本地同步状态(避免刷新延迟,直接修改位置缓存) | 					// 本地同步状态(避免刷新延迟) | ||||||
| 					posModel.setMemo(newMemo); | 					posModel.setMemo(newMemo); | ||||||
| 					posModel.setIsEnableRealPositionDistance(isDistanceEnable); | 					posModel.setIsEnableRealPositionDistance(isDistanceEnable); | ||||||
| 					posModel.setIsSimpleView(true); | 					posModel.setIsSimpleView(true); | ||||||
| 					notifyItemChanged(position); // 刷新当前项,显示更新后的状态 | 					notifyItemChanged(position); | ||||||
| 					hideSoftKeyboard(v); | 					hideSoftKeyboard(v); | ||||||
| 					LogUtils.d(TAG, "触发保存:位置ID=" + posId + ",新备注=" + newMemo + ",距离启用=" + isDistanceEnable); | 					LogUtils.d(TAG, "保存位置:ID=" + posId + ",新备注=" + newMemo + ",距离启用=" + isDistanceEnable); | ||||||
| 				} |  | ||||||
| 			}); |  | ||||||
|  |  | ||||||
|         // 8. 绑定任务视图(显示任务数量+新增任务,数据从MainService获取) |  | ||||||
|         bindTaskView(holder, posId); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 绑定任务视图(编辑模式专属:从MainService获取任务数据,新增任务调用服务接口) |  | ||||||
|      */ |  | ||||||
|     private void bindTaskView(final EditViewHolder holder, final String posId) { |  | ||||||
|         // 1. 从MainService获取当前位置的任务数量(Java 7 迭代器遍历服务数据) |  | ||||||
|         int taskCount = 0; |  | ||||||
|         MainService mainService = mMainServiceRef.get(); |  | ||||||
|         if (mainService != null) { |  | ||||||
|             ArrayList<PositionTaskModel> posTasks = mainService.getTasksByPositionId(posId); |  | ||||||
|             taskCount = (posTasks != null) ? posTasks.size() : 0; |  | ||||||
|         } |  | ||||||
|         // 显示任务数量(简化设计,实际可扩展为任务列表) |  | ||||||
|         holder.tvTaskCount.setText("任务数量:" + taskCount); |  | ||||||
|  |  | ||||||
|         // 2. 新增任务:调用MainService接口(不操作本地缓存,数据直接写入服务) |  | ||||||
|         holder.btnAddTask.setOnClickListener(new View.OnClickListener() { |  | ||||||
| 				@Override |  | ||||||
| 				public void onClick(View v) { |  | ||||||
| 					MainService mainService = mMainServiceRef.get(); |  | ||||||
| 					if (mainService == null) { |  | ||||||
| 						LogUtils.e(TAG, "新增任务失败:MainService已回收(弱引用失效)"); |  | ||||||
| 						return; |  | ||||||
| 					} |  | ||||||
|  |  | ||||||
| 					// 构建默认任务模型(Java 7 显式初始化) |  | ||||||
| 					PositionTaskModel newTask = new PositionTaskModel(); |  | ||||||
| 					newTask.setTaskId(PositionTaskModel.genTaskId()); // 生成唯一任务ID(需在PositionTaskModel实现静态方法) |  | ||||||
| 					newTask.setPositionId(posId);                     // 绑定当前位置ID |  | ||||||
| 					newTask.setTaskDescription(DEFAULT_TASK_DESC);    // 默认任务描述 |  | ||||||
| 					newTask.setIsEnable(true);                        // 默认启用任务 |  | ||||||
| 					newTask.setDiscussDistance(DEFAULT_TASK_DISTANCE);// 默认任务距离(50米) |  | ||||||
|  |  | ||||||
| 					// 调用MainService接口新增任务(数据写入服务,由服务处理持久化+通知刷新) |  | ||||||
| 					mainService.addTask(newTask); |  | ||||||
| 					hideSoftKeyboard(v); |  | ||||||
| 					LogUtils.d(TAG, "触发新增任务:调用MainService接口,位置ID=" + posId + ",任务ID=" + newTask.getTaskId()); |  | ||||||
| 				} | 				} | ||||||
| 			}); | 			}); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // ========================================================================= |     // ========================================================================= | ||||||
|     // 工具方法(Java 7 风格:无Lambda,纯匿名内部类+迭代器) |     // PositionTaskListView 集成(分简单/编辑模式,差异化初始化+绑定) | ||||||
|     // ========================================================================= |     // ========================================================================= | ||||||
|     /** |     /** | ||||||
|      * 更新距离显示(根据位置模型状态,显示不同文本+颜色) |      * 初始化+绑定简单模式任务列表视图(仅显示已启用任务,无编辑操作) | ||||||
|      */ |      */ | ||||||
|     private void updateDistanceDisplay(TextView distanceView, PositionModel posModel) { |     private void initAndBindSimpleTaskView(PositionTaskListView taskView, final String posId, MainService mainService) { | ||||||
|         if (distanceView == null || posModel == null) { |         if (taskView == null || TextUtils.isEmpty(posId) || mainService == null) { | ||||||
|             LogUtils.w(TAG, "updateDistanceDisplay:参数为空(控件/位置模型)"); |             LogUtils.w(TAG, "初始化简单模式任务视图失败:参数无效(posId=" + posId + ",service=" + mainService + ")"); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 场景1:距离未启用 |         // 1. 初始化任务视图(绑定MainService+当前位置ID,假设视图已实现init方法) | ||||||
|  |         taskView.init(mainService, posId); | ||||||
|  |         // 2. 设置为简单模式(仅展示,隐藏编辑按钮,需视图支持该状态设置) | ||||||
|  |         taskView.setViewStatus(PositionTaskListView.VIEW_MODE_SIMPLE); | ||||||
|  |         // 3. 同步任务数据(从MainService拉取当前位置已启用任务) | ||||||
|  |         taskView.syncTasksFromMainService(); | ||||||
|  |  | ||||||
|  |         // 4. 任务更新回调(服务任务变化时重新同步) | ||||||
|  |         taskView.setOnTaskUpdatedListener(new PositionTaskListView.OnTaskUpdatedListener() { | ||||||
|  | 				@Override | ||||||
|  | 				public void onTaskUpdated(String positionId, ArrayList<PositionTaskModel> updatedTasks) { | ||||||
|  | 					LogUtils.d(TAG, "简单模式任务更新:位置ID=" + positionId + ",已启用任务数=" + updatedTasks.size()); | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  |  | ||||||
|  |         LogUtils.d(TAG, "初始化简单模式任务视图完成:位置ID=" + posId); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 初始化+绑定编辑模式任务列表视图(支持增删改查,关联新增任务按钮) | ||||||
|  |      */ | ||||||
|  |     private void initAndBindEditTaskView(final PositionTaskListView taskView, final String posId,  | ||||||
|  |                                          MainService mainService, Button btnAddTask) { | ||||||
|  |         if (taskView == null || TextUtils.isEmpty(posId) || mainService == null || btnAddTask == null) { | ||||||
|  |             LogUtils.w(TAG, "初始化编辑模式任务视图失败:参数无效(posId=" + posId + ",btnAddTask=" + btnAddTask + ")"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 1. 初始化任务视图(绑定MainService+当前位置ID) | ||||||
|  |         taskView.init(mainService, posId); | ||||||
|  |         // 2. 设置为编辑模式(显示编辑/删除按钮,支持修改) | ||||||
|  |         taskView.setViewStatus(PositionTaskListView.VIEW_MODE_EDIT); | ||||||
|  |         // 3. 同步任务数据(从MainService拉取当前位置所有任务) | ||||||
|  |         taskView.syncTasksFromMainService(); | ||||||
|  |  | ||||||
|  |         // 4. 绑定“新增任务”按钮逻辑(点击创建默认任务,通过任务视图同步到服务) | ||||||
|  |         btnAddTask.setOnClickListener(new View.OnClickListener() { | ||||||
|  | 				@Override | ||||||
|  | 				public void onClick(View v) { | ||||||
|  | 					// 构建默认任务模型(关联当前位置ID,使用默认配置) | ||||||
|  | 					PositionTaskModel newTask = new PositionTaskModel(); | ||||||
|  | 					newTask.setTaskId(PositionTaskModel.genTaskId()); // 生成唯一任务ID(需模型类实现) | ||||||
|  | 					newTask.setPositionId(posId);                     // 绑定当前位置 | ||||||
|  | 					newTask.setTaskDescription(DEFAULT_TASK_DESC);    // 默认描述 | ||||||
|  | 					newTask.setDiscussDistance(DEFAULT_TASK_DISTANCE); // 默认触发距离(50米) | ||||||
|  | 					newTask.setIsEnable(true);                        // 默认启用 | ||||||
|  | 					newTask.setIsBingo(false);                        // 初始未触发 | ||||||
|  |  | ||||||
|  | 					// 调用任务视图的新增方法(假设视图已实现addNewTask,内部同步MainService) | ||||||
|  | 					taskView.addNewTask(newTask); | ||||||
|  | 					hideSoftKeyboard(v); // 隐藏软键盘,提升体验 | ||||||
|  | 					LogUtils.d(TAG, "编辑模式新增任务:位置ID=" + posId + ",任务ID=" + newTask.getTaskId()); | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  |  | ||||||
|  |         // 5. 任务更新回调(通知外部任务变化,如Activity需要联动) | ||||||
|  |         taskView.setOnTaskUpdatedListener(new PositionTaskListView.OnTaskUpdatedListener() { | ||||||
|  | 				@Override | ||||||
|  | 				public void onTaskUpdated(String positionId, ArrayList<PositionTaskModel> updatedTasks) { | ||||||
|  | 					LogUtils.d(TAG, "编辑模式任务更新:位置ID=" + positionId + ",当前任务数=" + updatedTasks.size()); | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  |  | ||||||
|  |         LogUtils.d(TAG, "初始化编辑模式任务视图完成:位置ID=" + posId); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // ========================================================================= | ||||||
|  |     // 工具方法(距离显示/数据校验/控件管理,Java 7 语法适配) | ||||||
|  |     // ========================================================================= | ||||||
|  |     /** | ||||||
|  |      * 更新距离显示(按状态区分文本和颜色,提升视觉区分度) | ||||||
|  |      */ | ||||||
|  |     private void updateDistanceDisplay(TextView distanceView, PositionModel posModel) { | ||||||
|  |         if (distanceView == null || posModel == null) { | ||||||
|  |             LogUtils.w(TAG, "更新距离显示失败:参数为空(控件/位置模型)"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 场景1:距离未启用(灰色文本) | ||||||
|         if (!posModel.isEnableRealPositionDistance()) { |         if (!posModel.isEnableRealPositionDistance()) { | ||||||
|             distanceView.setText(DISTANCE_DISABLED); |             distanceView.setText(DISTANCE_DISABLED); | ||||||
|             distanceView.setTextColor(mContext.getResources().getColor(R.color.gray)); |             distanceView.setTextColor(mContext.getResources().getColor(R.color.gray)); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 场景2:距离计算失败(用-1标记失败状态) |         // 场景2:距离计算失败(红色文本,用-1标记失败状态) | ||||||
|         double distance = posModel.getRealPositionDistance(); |         double distance = posModel.getRealPositionDistance(); | ||||||
|         if (distance < 0) { |         if (distance < 0) { | ||||||
|             distanceView.setText(DISTANCE_ERROR); |             distanceView.setText(DISTANCE_ERROR); | ||||||
| @@ -340,7 +416,7 @@ public class PositionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 场景3:正常显示距离(按距离范围设置颜色,提升视觉区分度) |         // 场景3:正常显示距离(按距离范围设置颜色) | ||||||
|         distanceView.setText(String.format(DISTANCE_FORMAT, distance)); |         distanceView.setText(String.format(DISTANCE_FORMAT, distance)); | ||||||
|         if (distance <= 100) { |         if (distance <= 100) { | ||||||
|             distanceView.setTextColor(mContext.getResources().getColor(R.color.green)); // 近距离(≤100米) |             distanceView.setTextColor(mContext.getResources().getColor(R.color.green)); // 近距离(≤100米) | ||||||
| @@ -352,11 +428,11 @@ public class PositionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 根据索引获取位置模型(从位置缓存取数,容错处理) |      * 根据索引获取位置模型(容错处理,避免越界/空指针) | ||||||
|      */ |      */ | ||||||
|     private PositionModel getPositionByIndex(int index) { |     private PositionModel getPositionByIndex(int index) { | ||||||
|         if (mCachedPositionList == null || index < 0 || index >= mCachedPositionList.size()) { |         if (mCachedPositionList == null || index < 0 || index >= mCachedPositionList.size()) { | ||||||
|             LogUtils.w(TAG, "getPositionByIndex:无效索引(" + index + ")或位置缓存为空"); |             LogUtils.w(TAG, "获取位置模型失败:无效索引(" + index + ")或缓存为空"); | ||||||
|             return null; |             return null; | ||||||
|         } |         } | ||||||
|         return mCachedPositionList.get(index); |         return mCachedPositionList.get(index); | ||||||
| @@ -367,18 +443,18 @@ public class PositionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde | |||||||
|      */ |      */ | ||||||
|     private int getPositionIndexById(String positionId) { |     private int getPositionIndexById(String positionId) { | ||||||
|         if (TextUtils.isEmpty(positionId) || mCachedPositionList == null || mCachedPositionList.isEmpty()) { |         if (TextUtils.isEmpty(positionId) || mCachedPositionList == null || mCachedPositionList.isEmpty()) { | ||||||
|             LogUtils.w(TAG, "getPositionIndexById:参数无效(位置ID/缓存为空)"); |             LogUtils.w(TAG, "获取位置索引失败:参数无效(ID/缓存为空)"); | ||||||
|             return -1; |             return -1; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Java 7 增强for循环遍历(替代Lambda,适配Java 7语法) |         // Java 7 增强for循环遍历(替代Lambda,适配语法) | ||||||
|         for (int i = 0; i < mCachedPositionList.size(); i++) { |         for (int i = 0; i < mCachedPositionList.size(); i++) { | ||||||
|             PositionModel pos = mCachedPositionList.get(i); |             PositionModel pos = mCachedPositionList.get(i); | ||||||
|             if (positionId.equals(pos.getPositionId())) { |             if (positionId.equals(pos.getPositionId())) { | ||||||
|                 return i; // 找到匹配ID,返回索引 |                 return i; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         LogUtils.w(TAG, "getPositionIndexById:未找到位置ID=" + positionId); |         LogUtils.w(TAG, "获取位置索引失败:未找到ID=" + positionId); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -386,57 +462,96 @@ public class PositionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde | |||||||
|      * 局部更新距离UI(仅更新指定位置的距离,避免全量刷新卡顿) |      * 局部更新距离UI(仅更新指定位置的距离,避免全量刷新卡顿) | ||||||
|      */ |      */ | ||||||
|     public void updateSinglePositionDistance(String positionId) { |     public void updateSinglePositionDistance(String positionId) { | ||||||
|         // 校验参数:位置ID无效或控件未缓存,直接返回 |         if (TextUtils.isEmpty(positionId) || mPosDistanceViewMap.isEmpty()) { | ||||||
|         if (TextUtils.isEmpty(positionId) || !mPosDistanceViewMap.containsKey(positionId)) { |             LogUtils.w(TAG, "局部更新距离失败:ID无效或无控件缓存(ID=" + positionId + ")"); | ||||||
|             LogUtils.w(TAG, "updateSinglePositionDistance:位置ID无效或控件未缓存(ID=" + positionId + ")"); |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 1. 获取服务端最新位置数据(带重试,避免服务临时回收) | ||||||
|  |         MainService mainService = getMainServiceWithRetry(2); | ||||||
|  |         if (mainService == null) { | ||||||
|  |             LogUtils.e(TAG, "局部更新距离失败:无法获取MainService"); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 从MainService获取最新位置模型(确保距离值是服务端最新) |  | ||||||
|         PositionModel latestPos = null; |         PositionModel latestPos = null; | ||||||
|         MainService mainService = mMainServiceRef.get(); |         try { | ||||||
|         if (mainService != null) { |  | ||||||
|             ArrayList<PositionModel> servicePosList = mainService.getPositionList(); |             ArrayList<PositionModel> servicePosList = mainService.getPositionList(); | ||||||
|             if (servicePosList != null && !servicePosList.isEmpty()) { |             if (servicePosList != null && !servicePosList.isEmpty()) { | ||||||
|                 // Java 7 迭代器遍历服务端位置列表,找到目标位置 |                 // Java 7 迭代器遍历,避免ConcurrentModificationException | ||||||
|                 Iterator<PositionModel> posIter = servicePosList.iterator(); |                 Iterator<PositionModel> iter = servicePosList.iterator(); | ||||||
|                 while (posIter.hasNext()) { |                 while (iter.hasNext()) { | ||||||
|                     PositionModel pos = posIter.next(); |                     PositionModel pos = iter.next(); | ||||||
|                     if (positionId.equals(pos.getPositionId())) { |                     if (positionId.equals(pos.getPositionId())) { | ||||||
|                         latestPos = pos; |                         latestPos = pos; | ||||||
|                         break; |                         break; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             LogUtils.d(TAG, "获取最新位置数据失败(ID=" + positionId + ")" + e); | ||||||
|  |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 用服务端最新距离更新UI(直接操作缓存的距离控件,无需刷新整个项) |         if (latestPos == null) { | ||||||
|         if (latestPos != null) { |             LogUtils.w(TAG, "局部更新距离失败:未找到位置ID=" + positionId); | ||||||
|             TextView distanceView = mPosDistanceViewMap.get(positionId); |             return; | ||||||
|             updateDistanceDisplay(distanceView, latestPos); |         } | ||||||
|             LogUtils.d(TAG, "局部更新距离完成:位置ID=" + positionId + ",最新距离=" + latestPos.getRealPositionDistance() + "米"); |  | ||||||
|  |         // 2. 更新距离控件(确保主线程操作,避免跨线程异常) | ||||||
|  |         final TextView distanceView = mPosDistanceViewMap.get(positionId); | ||||||
|  |         if (distanceView != null && distanceView.isAttachedToWindow()) { | ||||||
|  | 			final PositionModel finalLatestPos = latestPos; | ||||||
|  |             distanceView.post(new Runnable() { | ||||||
|  | 					@Override | ||||||
|  | 					public void run() { | ||||||
|  | 						updateDistanceDisplay(distanceView, finalLatestPos); | ||||||
|  | 					} | ||||||
|  | 				}); | ||||||
|  |             LogUtils.d(TAG, "局部更新距离完成:位置ID=" + positionId + ",距离=" + latestPos.getRealPositionDistance() + "米"); | ||||||
|         } else { |         } else { | ||||||
|             LogUtils.w(TAG, "局部更新距离失败:未在MainService找到位置ID=" + positionId); |             mPosDistanceViewMap.remove(positionId); // 移除无效控件缓存 | ||||||
|  |             LogUtils.w(TAG, "局部更新距离失败:控件已回收/脱离视图树(ID=" + positionId + ")"); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 全量更新位置数据(从MainService同步最新位置列表,刷新UI) |      * 全量更新位置数据(从服务同步最新数据,过滤无效/重复项) | ||||||
|      */ |      */ | ||||||
|     public void updateAllPositionData(ArrayList<PositionModel> newPosList) { |     public void updateAllPositionData(ArrayList<PositionModel> newPosList) { | ||||||
|         if (newPosList == null) { |         if (newPosList == null) { | ||||||
|             LogUtils.w(TAG, "updateAllPositionData:新位置列表为空,跳过更新"); |             LogUtils.w(TAG, "全量更新位置数据失败:新列表为空"); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 同步服务端最新位置数据到本地缓存 |         // 1. 过滤无效位置(校验核心字段:ID/经纬度合法) | ||||||
|  |         ArrayList<PositionModel> validPosList = new ArrayList<PositionModel>(); | ||||||
|  |         for (PositionModel pos : newPosList) { | ||||||
|  |             if (TextUtils.isEmpty(pos.getPositionId())  | ||||||
|  |                 || pos.getLongitude() < -180 || pos.getLongitude() > 180  | ||||||
|  |                 || pos.getLatitude() < -90 || pos.getLatitude() > 90) { | ||||||
|  |                 LogUtils.w(TAG, "过滤无效位置:ID=" + pos.getPositionId() + "(经纬度/ID非法)"); | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             validPosList.add(pos); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 2. 去重(按位置ID去重,保留服务端最新数据) | ||||||
|  |         ConcurrentHashMap<String, PositionModel> uniquePosMap = new ConcurrentHashMap<String, PositionModel>(); | ||||||
|  |         for (PositionModel pos : validPosList) { | ||||||
|  |             uniquePosMap.put(pos.getPositionId(), pos); // 相同ID覆盖,保留最新 | ||||||
|  |         } | ||||||
|  |         ArrayList<PositionModel> uniquePosList = new ArrayList<PositionModel>(uniquePosMap.values()); | ||||||
|  |  | ||||||
|  |         // 3. 同步到本地缓存+刷新UI | ||||||
|         this.mCachedPositionList.clear(); |         this.mCachedPositionList.clear(); | ||||||
|         this.mCachedPositionList.addAll(newPosList); |         this.mCachedPositionList.addAll(uniquePosList); | ||||||
|         // 清空旧距离控件缓存(避免引用失效控件) |         // 清空旧控件缓存(避免引用失效数据) | ||||||
|         mPosDistanceViewMap.clear(); |         mPosDistanceViewMap.clear(); | ||||||
|         // 通知RecyclerView全量刷新UI |         mSimpleTaskViewMap.clear(); | ||||||
|  |         mEditTaskViewMap.clear(); | ||||||
|         notifyDataSetChanged(); |         notifyDataSetChanged(); | ||||||
|         LogUtils.d(TAG, "全量更新位置数据完成:当前位置数量=" + mCachedPositionList.size() + "(数据来源:MainService)"); |         LogUtils.d(TAG, "全量更新位置数据完成:原数量=" + newPosList.size() + ",过滤后=" + uniquePosList.size()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -444,29 +559,83 @@ public class PositionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde | |||||||
|      */ |      */ | ||||||
|     private void hideSoftKeyboard(View view) { |     private void hideSoftKeyboard(View view) { | ||||||
|         if (mContext == null || view == null) { |         if (mContext == null || view == null) { | ||||||
|             LogUtils.w(TAG, "hideSoftKeyboard:参数为空(上下文/视图),无法隐藏键盘"); |             LogUtils.w(TAG, "隐藏软键盘失败:参数为空(上下文/视图)"); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Java 7 显式获取输入法服务,避免Lambda |  | ||||||
|         InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE); |         InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE); | ||||||
|         if (imm != null) { |         if (imm != null) { | ||||||
|             imm.hideSoftInputFromWindow(view.getWindowToken(), 0); // 强制隐藏软键盘 |             imm.hideSoftInputFromWindow(view.getWindowToken(), 0); // 强制隐藏 | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 带重试的服务获取(解决弱引用临时回收问题,最多重试2次) | ||||||
|  |      */ | ||||||
|  |     private MainService getMainServiceWithRetry(int retryCount) { | ||||||
|  |         MainService mainService = mMainServiceRef.get(); | ||||||
|  |         if (mainService != null) { | ||||||
|  |             return mainService; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 重试逻辑:每次间隔100ms,避免频繁重试 | ||||||
|  |         for (int i = 0; i < retryCount; i++) { | ||||||
|  |             try { | ||||||
|  |                 Thread.sleep(100); | ||||||
|  |                 mainService = mMainServiceRef.get(); | ||||||
|  |                 if (mainService != null) { | ||||||
|  |                     LogUtils.d(TAG, "重试获取MainService成功(第" + (i+1) + "次)"); | ||||||
|  |                     return mainService; | ||||||
|  |                 } | ||||||
|  |             } catch (InterruptedException e) { | ||||||
|  |                 LogUtils.d(TAG, "重试获取服务时线程被中断" + e); | ||||||
|  |                 Thread.currentThread().interrupt(); // 恢复中断状态 | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         LogUtils.e(TAG, "重试" + retryCount + "次后仍未获取到MainService"); | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // ========================================================================= |     // ========================================================================= | ||||||
|     // 实现 MainService.TaskUpdateListener 接口(服务任务变化时回调) |     // 实现 MainService.TaskUpdateListener 接口(服务任务变化时回调) | ||||||
|     // ========================================================================= |     // ========================================================================= | ||||||
|     @Override |     @Override | ||||||
|     public void onTaskUpdated() { |     public void onTaskUpdated() { | ||||||
|         LogUtils.d(TAG, "收到MainService任务更新通知(任务新增/删除/状态变化),刷新UI"); |         LogUtils.d(TAG, "收到MainService任务更新通知,同步所有任务列表视图"); | ||||||
|         // 任务数据变化时,全量刷新Adapter(确保任务数量等显示同步) |  | ||||||
|         notifyDataSetChanged(); |         // 1. 同步简单模式任务视图(仅显示已启用任务) | ||||||
|  |         if (!mSimpleTaskViewMap.isEmpty()) { | ||||||
|  |             Iterator<ConcurrentHashMap.Entry<String, PositionTaskListView>> iter = mSimpleTaskViewMap.entrySet().iterator(); | ||||||
|  |             while (iter.hasNext()) { | ||||||
|  |                 ConcurrentHashMap.Entry<String, PositionTaskListView> entry = iter.next(); | ||||||
|  |                 PositionTaskListView taskView = entry.getValue(); | ||||||
|  |                 if (taskView != null && taskView.isAttachedToWindow()) { | ||||||
|  |                     taskView.syncTasksFromMainService(); // 从服务同步最新任务 | ||||||
|  |                 } else { | ||||||
|  |                     iter.remove(); // 移除无效视图缓存 | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 2. 同步编辑模式任务视图(支持编辑的全量任务) | ||||||
|  |         if (!mEditTaskViewMap.isEmpty()) { | ||||||
|  |             Iterator<ConcurrentHashMap.Entry<String, PositionTaskListView>> iter = mEditTaskViewMap.entrySet().iterator(); | ||||||
|  |             while (iter.hasNext()) { | ||||||
|  |                 ConcurrentHashMap.Entry<String, PositionTaskListView> entry = iter.next(); | ||||||
|  |                 PositionTaskListView taskView = entry.getValue(); | ||||||
|  |                 if (taskView != null && taskView.isAttachedToWindow()) { | ||||||
|  |                     taskView.syncTasksFromMainService(); // 从服务同步最新任务 | ||||||
|  |                 } else { | ||||||
|  |                     iter.remove(); // 移除无效视图缓存 | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // ========================================================================= |     // ========================================================================= | ||||||
|     // 回调设置方法(供LocationActivity调用,绑定交互逻辑) |     // 回调设置方法(供Activity绑定交互逻辑) | ||||||
|     // ========================================================================= |     // ========================================================================= | ||||||
|     public void setOnDeleteClickListener(OnDeleteClickListener listener) { |     public void setOnDeleteClickListener(OnDeleteClickListener listener) { | ||||||
|         this.mOnDeleteListener = listener; |         this.mOnDeleteListener = listener; | ||||||
| @@ -477,69 +646,96 @@ public class PositionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // ========================================================================= |     // ========================================================================= | ||||||
|     // 资源释放(Activity销毁时调用,避免内存泄漏) |     // 资源释放(Activity销毁时调用,彻底释放引用,避免内存泄漏) | ||||||
|     // ========================================================================= |     // ========================================================================= | ||||||
|     public void release() { |     public void release() { | ||||||
|         // 1. 反注册MainService任务监听(解除与服务的绑定,避免内存泄漏) |         // 1. 反注册MainService任务监听(解除服务绑定) | ||||||
|         MainService mainService = mMainServiceRef.get(); |         MainService mainService = mMainServiceRef.get(); | ||||||
|         if (mainService != null) { |         if (mainService != null) { | ||||||
|             mainService.unregisterTaskUpdateListener(this); |             mainService.unregisterTaskUpdateListener(this); | ||||||
|             LogUtils.d(TAG, "已反注册MainService任务监听,避免内存泄漏"); |             LogUtils.d(TAG, "已反注册MainService任务监听"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 2. 清空本地缓存(解除控件/数据引用,帮助GC回收) |         // 2. 释放简单模式任务视图资源(清空数据+解绑监听,替代onDestroy()) | ||||||
|  |         if (!mSimpleTaskViewMap.isEmpty()) { | ||||||
|  |             Iterator<ConcurrentHashMap.Entry<String, PositionTaskListView>> iter = mSimpleTaskViewMap.entrySet().iterator(); | ||||||
|  |             while (iter.hasNext()) { | ||||||
|  |                 PositionTaskListView taskView = iter.next().getValue(); | ||||||
|  |                 if (taskView != null) { | ||||||
|  |                     taskView.clearData(); | ||||||
|  |                     taskView.setOnTaskUpdatedListener(null); | ||||||
|  |                 } | ||||||
|  |                 iter.remove(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 3. 释放编辑模式任务视图资源(清空数据+解绑监听,替代onDestroy()) | ||||||
|  |         if (!mEditTaskViewMap.isEmpty()) { | ||||||
|  |             Iterator<ConcurrentHashMap.Entry<String, PositionTaskListView>> iter = mEditTaskViewMap.entrySet().iterator(); | ||||||
|  |             while (iter.hasNext()) { | ||||||
|  |                 PositionTaskListView taskView = iter.next().getValue(); | ||||||
|  |                 if (taskView != null) { | ||||||
|  |                     taskView.clearData(); | ||||||
|  |                     taskView.setOnTaskUpdatedListener(null); | ||||||
|  |                 } | ||||||
|  |                 iter.remove(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 4. 清空其他缓存+置空引用 | ||||||
|         mPosDistanceViewMap.clear(); |         mPosDistanceViewMap.clear(); | ||||||
|         if (mCachedPositionList != null) { |         if (mCachedPositionList != null) { | ||||||
|             mCachedPositionList.clear(); |             mCachedPositionList.clear(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // 3. 置空回调实例(避免持有Activity引用导致内存泄漏) |  | ||||||
|         mOnDeleteListener = null; |         mOnDeleteListener = null; | ||||||
|         mOnSavePosListener = null; |         mOnSavePosListener = null; | ||||||
|  |  | ||||||
|         LogUtils.d(TAG, "Adapter资源已完全释放(缓存清空+监听反注册)"); |         LogUtils.d(TAG, "Adapter资源已完全释放(任务视图资源释放+缓存清空+引用置空)"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // ========================================================================= |     // ========================================================================= | ||||||
|     // 静态内部类:视图Holder(Java 7 静态内部类,不持有外部引用,避免内存泄漏) |     // 静态内部类:ViewHolder(与布局严格对应,避免外部引用导致内存泄漏) | ||||||
|     // ========================================================================= |     // ========================================================================= | ||||||
|     /** |     /** | ||||||
|      * 简单视图Holder(仅显示数据,对应布局:item_position_simple.xml) |      * 简单模式ViewHolder(对应 item_position_simple.xml,含简单模式任务列表视图) | ||||||
|      */ |      */ | ||||||
|     public static class SimpleViewHolder extends RecyclerView.ViewHolder { |     public static class SimpleViewHolder extends RecyclerView.ViewHolder { | ||||||
|         TextView tvSimpleLon;     // 经度显示控件 |         TextView tvSimpleLon;         // 经度显示 | ||||||
|         TextView tvSimpleLat;     // 纬度显示控件 |         TextView tvSimpleLat;         // 纬度显示 | ||||||
|         TextView tvSimpleMemo;    // 备注显示控件 |         TextView tvSimpleMemo;        // 备注显示 | ||||||
|         TextView tvSimpleDistance;// 实时距离显示控件 |         TextView tvSimpleDistance;    // 距离显示 | ||||||
|  |         PositionTaskListView ptlvSimpleTasks; // 简单模式任务列表视图 | ||||||
|  |  | ||||||
|         public SimpleViewHolder(View itemView) { |         public SimpleViewHolder(View itemView) { | ||||||
|             super(itemView); |             super(itemView); | ||||||
|             // 绑定布局控件(与XML中ID严格对应,避免运行时空指针) |             // 绑定布局控件(与XML中ID严格一致,避免运行时空指针) | ||||||
|             tvSimpleLon = (TextView) itemView.findViewById(R.id.tv_simple_longitude); |             tvSimpleLon = (TextView) itemView.findViewById(R.id.tv_simple_longitude); | ||||||
|             tvSimpleLat = (TextView) itemView.findViewById(R.id.tv_simple_latitude); |             tvSimpleLat = (TextView) itemView.findViewById(R.id.tv_simple_latitude); | ||||||
|             tvSimpleMemo = (TextView) itemView.findViewById(R.id.tv_simple_memo); |             tvSimpleMemo = (TextView) itemView.findViewById(R.id.tv_simple_memo); | ||||||
|             tvSimpleDistance = (TextView) itemView.findViewById(R.id.tv_simple_distance); |             tvSimpleDistance = (TextView) itemView.findViewById(R.id.tv_simple_distance); | ||||||
|  |             ptlvSimpleTasks = (PositionTaskListView) itemView.findViewById(R.id.ptlv_simple_tasks); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 编辑视图Holder(含编辑控件+功能按钮,对应布局:item_position_edit.xml) |      * 编辑模式ViewHolder(对应 item_position_edit.xml,含编辑模式任务列表视图) | ||||||
|      */ |      */ | ||||||
|     public static class EditViewHolder extends RecyclerView.ViewHolder { |     public static class EditViewHolder extends RecyclerView.ViewHolder { | ||||||
|         TextView tvEditLon;       // 经度显示控件(不可编辑) |         TextView tvEditLon;           // 经度显示(不可编辑) | ||||||
|         TextView tvEditLat;       // 纬度显示控件(不可编辑) |         TextView tvEditLat;           // 纬度显示(不可编辑) | ||||||
|         EditText etEditMemo;      // 备注编辑控件 |         EditText etEditMemo;          // 备注编辑 | ||||||
|         TextView tvEditDistance;  // 实时距离显示控件 |         TextView tvEditDistance;      // 距离显示 | ||||||
|         RadioGroup rgDistanceSwitch; // 距离启用/禁用开关组 |         RadioGroup rgDistanceSwitch;  // 距离启用/禁用开关 | ||||||
|         Button btnCancel;         // 取消编辑按钮 |         Button btnCancel;             // 取消编辑按钮 | ||||||
|         Button btnDelete;         // 删除位置按钮 |         Button btnDelete;             // 删除位置按钮 | ||||||
|         Button btnSave;           // 保存位置按钮 |         Button btnSave;               // 保存位置按钮 | ||||||
|         Button btnAddTask;        // 新增任务按钮 |         Button btnAddTask;            // 新增任务按钮 | ||||||
|         TextView tvTaskCount;     // 任务数量显示控件 |         TextView tvTaskCount;         // 任务数量显示(兼容旧布局,可隐藏) | ||||||
|  |         PositionTaskListView ptlvEditTasks; // 编辑模式任务列表视图 | ||||||
|  |  | ||||||
|         public EditViewHolder(View itemView) { |         public EditViewHolder(View itemView) { | ||||||
|             super(itemView); |             super(itemView); | ||||||
|             // 绑定布局控件(与XML中ID严格对应,避免运行时空指针) |             // 绑定布局控件(与XML中ID严格一致,避免运行时空指针) | ||||||
|             tvEditLon = (TextView) itemView.findViewById(R.id.tv_edit_longitude); |             tvEditLon = (TextView) itemView.findViewById(R.id.tv_edit_longitude); | ||||||
|             tvEditLat = (TextView) itemView.findViewById(R.id.tv_edit_latitude); |             tvEditLat = (TextView) itemView.findViewById(R.id.tv_edit_latitude); | ||||||
|             etEditMemo = (EditText) itemView.findViewById(R.id.et_edit_memo); |             etEditMemo = (EditText) itemView.findViewById(R.id.et_edit_memo); | ||||||
| @@ -550,7 +746,94 @@ public class PositionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde | |||||||
|             btnSave = (Button) itemView.findViewById(R.id.btn_edit_save); |             btnSave = (Button) itemView.findViewById(R.id.btn_edit_save); | ||||||
|             btnAddTask = (Button) itemView.findViewById(R.id.btn_add_task); |             btnAddTask = (Button) itemView.findViewById(R.id.btn_add_task); | ||||||
|             tvTaskCount = (TextView) itemView.findViewById(R.id.tv_task_count); |             tvTaskCount = (TextView) itemView.findViewById(R.id.tv_task_count); | ||||||
|  |             ptlvEditTasks = (PositionTaskListView) itemView.findViewById(R.id.ptlv_edit_tasks); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // ========================================================================= | ||||||
|  |     // 补充:PositionTaskListView 必要方法适配(确保视图类已实现以下基础方法) | ||||||
|  |     // (若视图类未实现,需在 PositionTaskListView 中添加对应逻辑) | ||||||
|  |     // ========================================================================= | ||||||
|  |     public static class PositionTaskListViewRequiredMethods { | ||||||
|  |         /** | ||||||
|  |          * 1. init 方法:初始化任务视图(绑定服务+位置ID) | ||||||
|  |          * 需在 PositionTaskListView 中添加: | ||||||
|  |          * public void init(MainService mainService, String positionId) { | ||||||
|  |          *     this.mMainServiceRef = new WeakReference<MainService>(mainService); // 弱引用服务 | ||||||
|  |          *     this.mPositionId = positionId; // 绑定当前位置ID | ||||||
|  |          * } | ||||||
|  |          */ | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * 2. setViewStatus 方法:设置视图模式(简单/编辑) | ||||||
|  |          * 需在 PositionTaskListView 中添加: | ||||||
|  |          * public static final int VIEW_MODE_SIMPLE = 0; // 仅显示 | ||||||
|  |          * public static final int VIEW_MODE_EDIT = 1;   // 可编辑 | ||||||
|  |          * private int mViewMode; | ||||||
|  |          * public void setViewStatus(int viewMode) { | ||||||
|  |          *     this.mViewMode = viewMode; | ||||||
|  |          *     // 根据模式控制编辑/删除按钮显示(如简单模式隐藏,编辑模式显示) | ||||||
|  |          *     updateButtonVisibility(); | ||||||
|  |          * } | ||||||
|  |          */ | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * 3. syncTasksFromMainService 方法:从服务同步任务数据 | ||||||
|  |          * 需在 PositionTaskListView 中添加: | ||||||
|  |          * public void syncTasksFromMainService() { | ||||||
|  |          *     MainService mainService = mMainServiceRef.get(); | ||||||
|  |          *     if (mainService == null || TextUtils.isEmpty(mPositionId)) return; | ||||||
|  |          *     // 根据视图模式拉取任务(简单模式:已启用;编辑模式:所有) | ||||||
|  |          *     ArrayList<PositionTaskModel> tasks = (mViewMode == VIEW_MODE_SIMPLE) | ||||||
|  |          *            ? mainService.getEnabledTasksByPositionId(mPositionId) | ||||||
|  |          *             : mainService.getTasksByPositionId(mPositionId); | ||||||
|  |          *     // 更新列表显示(如设置Adapter数据) | ||||||
|  |          *     setTaskList(tasks); | ||||||
|  |          * } | ||||||
|  |          */ | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * 4. addNewTask 方法:新增任务(同步服务+刷新列表) | ||||||
|  |          * 需在 PositionTaskListView 中添加: | ||||||
|  |          * public void addNewTask(PositionTaskModel newTask) { | ||||||
|  |          *     if (newTask == null || TextUtils.isEmpty(newTask.getPositionId())) return; | ||||||
|  |          *     MainService mainService = mMainServiceRef.get(); | ||||||
|  |          *     if (mainService != null) { | ||||||
|  |          *         mainService.addTask(newTask); | ||||||
|  |          *         syncTasksFromMainService(); // 新增后同步刷新 | ||||||
|  |          *         Toast.makeText(getContext(), "任务创建成功", Toast.LENGTH_SHORT).show(); | ||||||
|  |          *     } else { | ||||||
|  |          *         Toast.makeText(getContext(), "新增失败,请重试", Toast.LENGTH_SHORT).show(); | ||||||
|  |          *     } | ||||||
|  |          * } | ||||||
|  |          */ | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * 5. clearData 方法:清空任务数据(释放资源) | ||||||
|  |          * 需在 PositionTaskListView 中添加: | ||||||
|  |          * public void clearData() { | ||||||
|  |          *     if (mTaskList != null) mTaskList.clear(); // 清空任务列表数据 | ||||||
|  |          *     if (mTaskAdapter != null) mTaskAdapter.notifyDataSetChanged(); // 刷新列表 | ||||||
|  |          * } | ||||||
|  |          */ | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * 6. setOnTaskUpdatedListener 方法:设置任务更新回调 | ||||||
|  |          * 需在 PositionTaskListView 中添加: | ||||||
|  |          * public interface OnTaskUpdatedListener { | ||||||
|  |          *     void onTaskUpdated(String positionId, ArrayList<PositionTaskModel> updatedTasks); | ||||||
|  |          * } | ||||||
|  |          * private OnTaskUpdatedListener mTaskUpdateListener; | ||||||
|  |          * public void setOnTaskUpdatedListener(OnTaskUpdatedListener listener) { | ||||||
|  |          *     this.mTaskUpdateListener = listener; | ||||||
|  |          * } | ||||||
|  |          * // 任务变化时调用(如同步后/编辑后) | ||||||
|  |          * private void notifyTaskUpdated(ArrayList<PositionTaskModel> updatedTasks) { | ||||||
|  |          *     if (mTaskUpdateListener != null) { | ||||||
|  |          *         mTaskUpdateListener.onTaskUpdated(mPositionId, updatedTasks); | ||||||
|  |          *     } | ||||||
|  |          * } | ||||||
|  |          */ | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 ZhanGSKen
					ZhanGSKen