You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用SharedPreferences传递Api嵌套数组至Activity并实现数据追加?

解决SharedPreferences存储复杂嵌套数组的问题

嘿,我懂你现在的困扰——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)需要满足两个条件:

  1. 必须有无参构造函数(Gson需要用它来创建对象);
  2. 字段名要和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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:25:48