Android Activity间传递自定义对象列表如何用Gson实现?

来源:建站教程作者:越南程序员头衔:程序员
导读:本期聚焦于小伙伴创作的《Android Activity间传递自定义对象列表如何用Gson实现?》,敬请观看详情。直接把自定义对象列表塞进Intent在Android里行不通,因为Intent extras只接受可序列化或基础类型。借助Gson把对象列表转成JSON字符串再传递,是避开Parcelable模板代码的务实做法。先通过Gson实例将List序列化为字符串放入Intent,目标Activity取出后反序列化为原类型。要注意Gson默认依赖无参构造与字段反射,复杂泛型可用TypeToken保留类型信息。相比Parcelable,该方案开发成本低但运行时多一次解析开销,适合数据量小、跨页面临时传值场景,切勿用于大数据或高频通信。

在Android开发中,Activity之间的页面跳转经常需要携带数据,而当我们要传递的是一个自定义对象的列表时,直接使用Intent的putExtra方法会抛出异常,因为Android的Binder机制并不支持任意Java对象直接跨进程或跨组件传输。借助Gson这类JSON序列化库,可以把对象列表转换为字符串,从而绕开系统对数据类型的限制。这种方式不需要为每个类编写Parcelable接口,尤其适合快速开发或字段较多的数据模型。

Android Activity间传递自定义对象列表如何用Gson实现?

为什么不能直接传递自定义对象列表

Android的Intent在启动Activity时,会把附加数据存放在Bundle中,而Bundle底层依赖Parcel机制。系统只允许放入基本类型、String、以及实现了Serializable或Parcelable接口的对象。如果我们定义了一个普通的Java类,例如User,即便它内部只有几个字段,只要没有实现上述接口,调用intent.putExtra("list", userList)就会在运行时报错,提示该类型无法序列化。

有些开发者会选择让类实现Serializable接口,但这种方式依赖Java默认反射序列化,不仅效率偏低,还容易因为字段变更导致反序列化失败。Parcelable虽然性能更好,却要求手写大量的describeContents和writeToParcel方法,当模型字段很多时维护成本很高。因此,把对象列表转为JSON字符串,用String类型携带,成为了一种兼顾开发效率和可读性的替代方案。

Gson序列化的基本用法

假设我们有一个自定义数据类,用来表示用户简要信息。这个类不需要实现任何特殊接口,只要字段有对应的getter或者本身是public的,Gson就能通过反射完成转换。下面先给出数据类的定义,注意这里只是普通Java类。

public class User {
    private String name;
    private int age;
    private String email;

    public User(String name, int age, String email) {
        this.name = name;
        this.age = age;
        this.email = email;
    }

    // Gson需要通过无参构造或字段直接访问,这里省略getter/setter示意
}

在发送端的Activity中,我们创建Gson实例,并调用toJson方法把List<User>变成字符串,然后放入Intent。Gson的toJson可以接受任意对象,包括泛型集合,它在内部通过反射读取字段值并拼装为符合JSON规范的文本。

import com.google.gson.Gson;
import java.util.ArrayList;
import java.util.List;

List<User> userList = new ArrayList<>();
userList.add(new User("张三", 20, "zhangsan@ipipp.com"));
userList.add(new User("李四", 25, "lisi@ipipp.com"));

Gson gson = new Gson();
String json = gson.toJson(userList);

Intent intent = new Intent(this, TargetActivity.class);
intent.putExtra("user_list_json", json);
startActivity(intent);

接收端的Activity在onCreate里通过getIntent().getStringExtra拿到JSON文本,再用Gson的fromJson还原为列表。这里由于泛型擦除,直接写new ArrayList<User>().getClass()无法保留泛型,因此更稳妥的做法是使用TypeToken来明确目标类型。

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.List;

String json = getIntent().getStringExtra("user_list_json");
Gson gson = new Gson();
Type type = new TypeToken<List<User>>(){}.getType();
List<User> userList = gson.fromJson(json, type);
</script>

处理泛型与复杂对象的注意点

上面的TypeToken写法是Gson处理泛型列表的标准方式。花括号创建一个匿名子类,getType()可以保留父类中声明的泛型参数,这样反序列化时Gson才知道每个元素应是User而不是LinkedTreeMap。如果列表里嵌套了其他自定义对象,例如User里包含一个Address类,只要Address也是普通类且字段可被访问,Gson会递归处理,无需额外配置。

需要提醒的是,如果模型使用了Kotlin的data class并且启用了混淆,要在proguard规则里保留类名和字段,否则release包会出现字段变成null的情况。此外,Gson默认通过字段名匹配JSON,若后端字段命名风格不同,可以用@SerializedName注解做映射,但不建议在页面间传递这种带网络模型的类,最好定义专门的UI模型以减少耦合。

与Parcelable方案的对比分析

为了更直观地理解两种方案的差异,我们可以从开发成本、运行效率和适用场景几个维度进行比较。下面的表格列出了主要区别。

维度Gson字符串传递Parcelable实现
代码量仅需toJson/fromJson,几乎无模板每个类需实现接口并写读写逻辑
运行开销有反射与字符串解析成本底层二进制写入,性能更高
类型安全依赖TypeToken,易因擦除出错编译期确定结构
适用数据量小列表或临时传值较大数据或高频传递

从表中可以看出,Gson方案最大的优势是省事,特别适合内部模块之间临时丢一小撮数据。但因为它要经过对象到字符串、字符串再到对象的两次转换,如果列表里有上千条记录,不仅占用Intent缓冲区(Binder事务有大小限制,通常约1MB),还容易造成页面跳转卡顿。

因此在实际项目中,如果对象列表很大,更合理的做法是把数据存入ViewModel、单例缓存或者本地数据库,Intent只传一个ID或索引。Gson传递应作为轻量级补充手段,而不是万能解法。

常见误区与避坑建议

一个常见误区是认为Intent可以无限塞数据,于是把整个接口响应的List直接用Gson转了传过去。其实Binder事务缓冲区非常有限,传输大JSON极易触发TransactionTooLargeException,而且接收页被系统回收后再恢复时,过大的状态保存也会失败。建议只传必要字段,或者在onSaveInstanceState里也不要缓存这种大字符串。

另一个坑是忘记处理null。若JSON字符串为空或格式损坏,gson.fromJson会返回null或抛异常,接收端应做防御性判断,避免后续代码出现空指针。对于必须可靠传递的场景,可以封装一个工具类,统一处理序列化失败时的默认值返回,让业务代码更健壮。

public class IntentJsonUtils {
    private static final Gson GSON = new Gson();

    public static void putList(Intent intent, String key, Object list) {
        intent.putExtra(key, GSON.toJson(list));
    }

    public static <T> List<T> getList(Intent intent, String key, Class<T> itemClass) {
        String json = intent.getStringExtra(key);
        if (json == null) {
            return new ArrayList<>();
        }
        Type type = com.google.gson.reflect.TypeToken.getParameterized(List.class, itemClass).getType();
        List<T> result = GSON.fromJson(json, type);
        return result != null ? result : new ArrayList<>();
    }
}

上述工具类利用TypeToken.getParameterized在运行时构造带元素类型的List泛型,比手写匿名类更简洁,也方便在多个Activity间复用。只需在跳转和接收时调用对应方法,就能把Gson传递的细节隐藏起来,降低出错概率。

AndroidActivity Gson修改时间:2026-08-01 17:03:33

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。