如何用SharedPreferences传递Api嵌套数组至Activity并实现数据追加?
嘿,我懂你现在的困扰——SharedPreferences本身只能存基本数据类型和字符串,直接把ArrayList或者自定义对象丢进去肯定拿不到有效数据,因为你看到的com.samuel.booking.entity.Product@e8f6200只是对象的默认toString()输出,根本不是实际的内容。下面给你两种靠谱的解决方案,按需选择:
方案一:用Gson序列化对象为JSON字符串(适合持久化保存)
如果需要把数据持久化保存(比如App重启后还要继续编辑),最方便的方式是用Gson把你的Log对象(包含嵌套的Student、Borrow、Book)直接序列化成JSON字符串,再存入SharedPreferences。
步骤1:添加Gson依赖
在你的app/build.gradle里添加Gson的依赖:
dependencies { implementation 'com.google.code.gson:gson:2.10.1' }
步骤2:序列化并存储选中的Log对象
在列表项点击事件里,把选中的Log对象转成JSON字符串存入SharedPreferences:
updtedlist.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long offset) { Log logItem = (Log) adapter.getItem(position); // 用Gson把Log对象转成JSON字符串 Gson gson = new Gson(); String logJson = gson.toJson(logItem); // 存入SharedPreferences SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences.Editor editor = settings.edit(); editor.putString("selected_log", logJson); editor.apply(); // 启动新Activity Intent i = new Intent(LogsActivity.this, LogInfoActivity.class); startActivity(i); } });
步骤3:在新Activity中读取并反序列化
在LogInfoActivity里取出JSON字符串,转回到Log对象:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_log_info); // 从SharedPreferences读取JSON SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); String logJson = settings.getString("selected_log", null); if (logJson != null) { Gson gson = new Gson(); Log logItem = gson.fromJson(logJson, Log.class); // 现在你可以正常使用所有嵌套数据了 Student student = logItem.getbookBorrower(); ArrayList<Borrow> borrowList = logItem.getContents(); // 比如遍历borrowList获取书籍信息 for (Borrow borrow : borrowList) { Book book = borrow.getBook(); Log.v("Book Name", book.getName()); } } }
注意事项:实体类要适配Gson序列化
你的自定义实体类(Log、Student、Borrow、Book)需要满足两个条件:
- 必须有无参构造函数(Gson需要用它来创建对象);
- 字段名要和JSON里的键对应,或者用
@SerializedName注解映射。比如Log类里的student_details字段:
public class Log { private String id; private String status; // ...其他字段 // 用注解映射JSON里的"student_details"键到当前字段 @SerializedName("student_details") private Student bookBorrower; @SerializedName("log_contents") private ArrayList<Borrow> contents; // 必须要有无参构造函数 public Log() {} // 你的其他构造函数、getter和setter }
步骤4:修改数据后重新保存
当你在LogInfoActivity里添加了新数据,只需重新序列化并覆盖存入SharedPreferences即可:
// 假设你已经修改了logItem里的内容 Gson gson = new Gson(); String updatedLogJson = gson.toJson(logItem); SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences.Editor editor = settings.edit(); editor.putString("selected_log", updatedLogJson); editor.apply(); // 之后就可以把updatedLogJson提交到服务器了
方案二:用Parcelable通过Intent传递(适合临时跳转)
如果只是在两个Activity之间临时传递数据,不需要持久化,用Parcelable比SharedPreferences更高效,也更直接。
步骤1:给实体类实现Parcelable
以Log类为例,你可以用Android Studio的自动生成功能(右键类名 → Generate → Parcelable)来快速实现,也可以手动写:
public class Log implements Parcelable { private String id; private String status; private Student bookBorrower; private ArrayList<Borrow> contents; // 无参构造函数 public Log() {} // 从Parcel读取数据的构造函数 protected Log(Parcel in) { id = in.readString(); status = in.readString(); bookBorrower = in.readParcelable(Student.class.getClassLoader()); contents = in.createTypedArrayList(Borrow.CREATOR); } public static final Creator<Log> CREATOR = new Creator<Log>() { @Override public Log createFromParcel(Parcel in) { return new Log(in); } @Override public Log[] newArray(int size) { return new Log[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(id); dest.writeString(status); dest.writeParcelable(bookBorrower, flags); dest.writeTypedList(contents); } // 你的getter和setter方法 }
注意:Student和Borrow、Book类也需要同样实现Parcelable接口。
步骤2:通过Intent传递对象
在列表点击事件里直接把Log对象放到Intent里:
updtedlist.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long offset) { Log logItem = (Log) adapter.getItem(position); Intent i = new Intent(LogsActivity.this, LogInfoActivity.class); i.putExtra("selected_log", logItem); // 直接传递Parcelable对象 startActivity(i); } });
步骤3:在新Activity中获取对象
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_log_info); Log logItem = getIntent().getParcelableExtra("selected_log"); if (logItem != null) { // 正常使用数据即可 Student student = logItem.getbookBorrower(); ArrayList<Borrow> borrowList = logItem.getContents(); } }
额外建议:更适合复杂数据的持久化方案
如果你的数据量比较大,或者需要频繁修改查询,Room数据库会比SharedPreferences更合适——它是Android官方推荐的本地数据库,支持结构化查询,性能更好,也更容易管理复杂数据模型。
内容的提问来源于stack exchange,提问作者Ayomikun Samuel

