当前位置: 首页 > news >正文

基于LiveData和ViewModel的路线管理实现(带PopupWindow删除功能)

包含RecyclerView绑定、PopupWindow删除功能和SharedPreferences持久化存储。

1. RouteInfo类(实现Parcelable接口)

java

复制

下载

import android.os.Parcel;
import android.os.Parcelable;public class RouteInfo implements Parcelable {private Integer routeID;private Integer routeState;private String name;private String mapInfo; // 简化存储private String routeTraceFilePath;private Double routeLength;private String routeBeginPhoto;private String routeEndPhoto;private Integer routeTimeCost;private int routeThumbnailImgPath;// 构造方法public RouteInfo() {}protected RouteInfo(Parcel in) {routeID = in.readInt();routeState = in.readInt();name = in.readString();mapInfo = in.readString();routeTraceFilePath = in.readString();routeLength = in.readDouble();routeBeginPhoto = in.readString();routeEndPhoto = in.readString();routeTimeCost = in.readInt();routeThumbnailImgPath = in.readInt();}public static final Creator<RouteInfo> CREATOR = new Creator<RouteInfo>() {@Overridepublic RouteInfo createFromParcel(Parcel in) {return new RouteInfo(in);}@Overridepublic RouteInfo[] newArray(int size) {return new RouteInfo[size];}};// Getter和Setter方法public Integer getRouteID() { return routeID; }public void setRouteID(Integer routeID) { this.routeID = routeID; }// 其他getter/setter省略...@Overridepublic int describeContents() { return 0; }@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeInt(routeID);dest.writeInt(routeState);dest.writeString(name);dest.writeString(mapInfo);dest.writeString(routeTraceFilePath);dest.writeDouble(routeLength);dest.writeString(routeBeginPhoto);dest.writeString(routeEndPhoto);dest.writeInt(routeTimeCost);dest.writeInt(routeThumbnailImgPath);}
}

2. ViewModel类(管理路线数据)

java

复制

下载

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import java.util.ArrayList;
import java.util.List;public class RouteViewModel extends ViewModel {private MutableLiveData<List<RouteInfo>> routeListLiveData;private List<RouteInfo> routeList = new ArrayList<>();public LiveData<List<RouteInfo>> getRouteList() {if (routeListLiveData == null) {routeListLiveData = new MutableLiveData<>();loadRoutes();}return routeListLiveData;}private void loadRoutes() {// 这里可以从SharedPreferences加载数据routeListLiveData.setValue(new ArrayList<>(routeList));}public void addRoute(RouteInfo route) {routeList.add(route);routeListLiveData.setValue(new ArrayList<>(routeList));}public void deleteRoute(int position) {if (position >= 0 && position < routeList.size()) {routeList.remove(position);routeListLiveData.setValue(new ArrayList<>(routeList));}}
}

3. SharedPreferences工具类

java

复制

下载

import android.content.Context;
import android.content.SharedPreferences;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;public class RoutePrefsUtil {private static final String PREFS_NAME = "route_prefs";private static final String ROUTE_LIST_KEY = "route_list";public static void saveRoutes(Context context, List<RouteInfo> routes) {SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);SharedPreferences.Editor editor = prefs.edit();Gson gson = new Gson();String json = gson.toJson(routes);editor.putString(ROUTE_LIST_KEY, json);editor.apply();}public static List<RouteInfo> loadRoutes(Context context) {SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);String json = prefs.getString(ROUTE_LIST_KEY, null);if (json == null) return new ArrayList<>();Gson gson = new Gson();Type type = new TypeToken<ArrayList<RouteInfo>>() {}.getType();return gson.fromJson(json, type);}
}

4. RecyclerView Adapter(带PopupWindow)

java

复制

下载

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;public class RouteListAdapter extends RecyclerView.Adapter<RouteListAdapter.RouteViewHolder> {private List<RouteInfo> routeList;private OnRouteClickListener listener;private Context context;public interface OnRouteClickListener {void onRouteClick(int position);void onDeleteClick(int position);}public RouteListAdapter(Context context, List<RouteInfo> routeList, OnRouteClickListener listener) {this.context = context;this.routeList = routeList;this.listener = listener;}@NonNull@Overridepublic RouteViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_route, parent, false);return new RouteViewHolder(view);}@Overridepublic void onBindViewHolder(@NonNull RouteViewHolder holder, int position) {RouteInfo route = routeList.get(position);holder.tvRouteName.setText(route.getName());holder.tvRouteLength.setText(String.format("%.2f 米", route.getRouteLength()));holder.ivMore.setOnClickListener(v -> showPopupWindow(v, position));}private void showPopupWindow(View anchorView, int position) {View popupView = LayoutInflater.from(context).inflate(R.layout.popup_route_options, null);PopupWindow popupWindow = new PopupWindow(popupView,ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT,true);popupView.findViewById(R.id.btn_delete).setOnClickListener(v -> {listener.onDeleteClick(position);popupWindow.dismiss();});popupWindow.showAsDropDown(anchorView);}@Overridepublic int getItemCount() {return routeList.size();}static class RouteViewHolder extends RecyclerView.ViewHolder {TextView tvRouteName;TextView tvRouteLength;ImageView ivMore;public RouteViewHolder(@NonNull View itemView) {super(itemView);tvRouteName = itemView.findViewById(R.id.tv_route_name);tvRouteLength = itemView.findViewById(R.id.tv_route_length);ivMore = itemView.findViewById(R.id.iv_more);}}
}

5. 在Activity/Fragment中使用

java

复制

下载

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;public class RouteListActivity extends AppCompatActivity {private RouteViewModel viewModel;private RouteListAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_route_list);RecyclerView recyclerView = findViewById(R.id.recycler_view);recyclerView.setLayoutManager(new LinearLayoutManager(this));viewModel = new ViewModelProvider(this).get(RouteViewModel.class);// 从SharedPreferences加载数据List<RouteInfo> savedRoutes = RoutePrefsUtil.loadRoutes(this);if (!savedRoutes.isEmpty()) {viewModel.getRouteList().observe(this, routes -> {adapter = new RouteListAdapter(this, routes, new RouteListAdapter.OnRouteClickListener() {@Overridepublic void onRouteClick(int position) {// 处理路线点击}@Overridepublic void onDeleteClick(int position) {viewModel.deleteRoute(position);RoutePrefsUtil.saveRoutes(RouteListActivity.this, viewModel.getRouteList().getValue());}});recyclerView.setAdapter(adapter);});for (RouteInfo route : savedRoutes) {viewModel.addRoute(route);}}}
}

6. 布局文件

item_route.xml (RecyclerView item布局)

xml

复制

下载

运行

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:padding="16dp"><LinearLayoutandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:orientation="vertical"><TextViewandroid:id="@+id/tv_route_name"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16sp"/><TextViewandroid:id="@+id/tv_route_length"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="14sp"/></LinearLayout><ImageViewandroid:id="@+id/iv_more"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@android:drawable/ic_menu_more"android:padding="8dp"/>
</LinearLayout>

popup_route_options.xml (PopupWindow布局)

xml

复制

下载

运行

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"android:background="@android:color/white"android:elevation="8dp"><Buttonandroid:id="@+id/btn_delete"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="删除路线"android:minWidth="120dp"android:background="?attr/selectableItemBackground"/>
</LinearLayout>

实现说明

  1. 数据管理:使用ViewModel管理路线数据,LiveData实现数据观察

  2. 持久化存储:通过SharedPreferences保存路线列表,使用Gson进行序列化

  3. 删除功能:通过PopupWindow实现删除按钮,点击后从列表移除并更新存储

  4. UI更新:RecyclerView自动响应数据变化

使用时请确保在build.gradle中添加了必要的依赖:

gradle

复制

下载

implementation 'androidx.lifecycle:lifecycle-viewmodel:2.3.1'
implementation 'androidx.lifecycle:lifecycle-livedata:2.3.1'
implementation 'com.google.code.gson:gson:2.8.6'

相关文章:

  • 【神经网络与深度学习】流模型的通俗易懂的原理
  • Simon J.D. Prince《Understanding Deep Learning》
  • vscode连接WSL卡住
  • jvm调优以及常见jvm问题解决等
  • chrono类 根据duration 类的周期类型得到对应的周期名称
  • 基于AI大语言模型的历史文献分析在气候与灾害重建中的技术-以海南岛千年台风序列重建为例
  • 现代生活中的健康养生之道
  • 传统Spring MVC + RESTful 与 Vue3 结合 JWT Token 验证的示例
  • 双检锁(Double-Checked Locking)单例模式
  • 管理会议最佳实践:高效协同与价值最大化
  • 卫星互联网:构建全球无缝通信网络的未来
  • C#SQLServer数据库通用访问类
  • Seata源码—8.Seata Saga模式的事务处理二
  • 线程、线程池、异步
  • OpenHarmony外设驱动使用 (九),Pin_auth
  • [Harmony]自定义导航栏
  • OpenHarmony外设驱动使用 (十),Sensor
  • DeepSeek 的强化学习优化策略:RLHF 与 DPO 的应用
  • canvas(二)-动画(2d)
  • 如果有三个服务实例部署在三台不同的服务器上,这三个服务实例的本地缓存,是存储一模一样的数据?还是各自只存一部分?
  • 湖北网站建设营销qq/seo实战技巧100例
  • 公司注册网站官网/2023年的新闻十条
  • 沈阳网站排名seo/竞价推广开户电话
  • 猪八戒网怎么做网站/关键词搜索量怎么查
  • 云南网站开发建设/百度登录入口
  • 网站规划与开发技术/同城推广有什么平台