Activity之间的数据传递方法汇总

本文详细介绍了在Android应用开发中,如何通过Intent、Serializable、Parcelable以及SharedPreferences等方式进行不同类型的参数传递,包括基本类型、复杂类型和自定义类型,以及注意事项和适用场景。
摘要由CSDN通过智能技术生成

8种基本类型及其包装类对应关系如下:

容我煮个栗子:

假设有 Activity1,Activity2 两个 Activity;如果要在 Activity1 中启动 Activity2,并传过去几个基本类型的数据,就可以这么写:

Intent intent = new Intent(this, Activity2.class);
intent.putExtra(String name, boolean value);
intent.putExtra(String name, byte value);
intent.putExtra(String name, char value);
intent.putExtra(String name, short value);
intent.putExtra(String name, int value);
intent.putExtra(String name, float value);
intent.putExtra(String name, long value);
intent.putExtra(String name, double value);
startActivity(intent);

在 Activity2 的 onCreate 中就可以通过如下方式接收:

Intent intent = getIntent();
boolean bool = intent.getBooleanExtra(String name, boolean defaultValue);
byte bt = intent.getByteExtra(String name, byte defaultValue);
char ch = intent.getCharExtra(String name, char defaultValue);
short sh = intent.getShortExtra(String name, short defaultValue);
int i = intent.getIntExtra(String name, int defaultValue);
float fl = intent.getFloatExtra(String name, float defaultValue);
long lg = intent.getLongExtra(String name, long defaultValue);
double db = intent.getDoubleExtra(String name, double defaultValue);

PS:上面发送和接收的时候,同一个字段必须使用相同的 name,比如:intent.putExtra(“BOOLEAN”, true);intent.getBooleanExtra(“BOOLEAN”, false);

1.2、复杂数据类型传递

Java 中也定义了一些常用的复杂类型,比如 String、基本数据类型的数组、ArrayList、HashMap 等等,Intent 也对它们做了支持,使得我们能很容易的通过 Intent 传递这些复杂类型。方法与上面基本类型类似,比如:

intent.putExtra(String name, String value);
intent.putExtra(String name, int[] value);
intent.putExtra(String name, Parcelable value);
intent.putExtra(String name, Serializable value);
intent.putExtra(String name, CharSequence value);
intent.putStringArrayListExtra(String name, ArrayList value);

接收方式也类似,这里就不再一一列举了。

不过,像 ArrayList、HashMap 这种,本身还能存放复杂类型的数据结构,要想通过 Intent 传递,得确保它们内部存放的类型也是能支持序列化和反序列化的。

1.3、自定义数据类型传递

上面已经列举了很多 Intent 支持的类型,但是默认提供的这些类型,总归是不够用的,很多时候我们会定义自己的数据类型,比如定义一个 Student:

public class Student{
public String name;
public int age;
}

那么这个时候我们应该如何通过Intent来传递呢?

1.3.1、实现 Serializable 接口

我们先看一下默认提供并被 Intent 支持的复杂数据类型的实现方式:

public final class String
implements java.io.Serializable, Comparable, CharSequence
public class ArrayList extends AbstractList
implements List, RandomAccess, Cloneable, java.io.Serializable
public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable

我们可以看到它们有一个共同的特点,都 implement 了 Serializable 接口。

Serializable 是一个空接口,它没有定义任何方法,知识用来标记其实现类是支持序列化和反序列化的。

因此当我们想让自定义的类型也能通过 Intent 传递时,只需要让该类实现 Serializable 接口即可。

依旧用 Student 来煮个栗子:

public class Student implements Serializable{
private static final long serialVersionUID = 1L;
public String name;
public int age;
}

传递方法就是:

intent.putExtra(String name, Serializable value);
intent.getSerializableExtra(String name);

PS:关于 Serializable 还有一些知识点,比如:serialVersionUID、静态变量序列化、transient 关键字、继承问题等等,这里就不介绍了,有兴趣的可以自行去查阅。

1.3.2、实现 Parcelable 接口

上面介绍了 Serializable 接口,但 Serializable 是 Java 的实现,Android 下能正常使用,没毛病,但 Google 觉得 Serializable 在 Android 内存不大性能不强的情况下的效率不太够,于是为 Android 量身定制了一个专用的接口——Parcelable。

还是用 Student 来煮栗子:

要想实现 Parcelable 接口,只需要先写好 Student 类和属性,然后让 Student 实现Parcelable,再然后根据 AS 的两步提示:第一步重写 describeContents 和 writeToParcel,第二步创建 CREATOR 就大功告成了。写好的类如下:

public class Student implements Parcelable{
public String name;
public int age;
protected Student(Parcel in) {
name = in.readString();
age = in.readInt();
}
public static final Creator CREATOR = new Creator() {
@Override
public Student createFromParcel(Parcel in) {
return new Student(in);
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
}

此时通过 Intent 去传递就可以使用如下方法:

intent.putExtra(String name, Parcelable value);
intent.getParcelableExtra(String name);

这两种实现序列化的方法的使用原则:

1)在使用内存的时候,Parcelable 比 Serializable 性能高,所以推荐使用 Parcelable。

2)Serializable 在序列化的时候会产生大量的临时变量,从而引起频繁的 GC。

3)Parcelable 不能使用在要将数据存储在磁盘上的情况,因为 Parcelable 不能很好的保证数据的持续性在外界有变化的情况下。尽管 Serializable 效率低点,但此时还是建议使用 Serializable 。

PS:Intent 还支持通过 Bundle 封装数据,然后传递 Bundle,但是查看 intent.putExtra 的实现,我们会发现,其实 intent.putExtra 的内部也是维护的一个 Bundle,因此,通过 putExtra 放入的数据,取出时也可以通过 Bundle 去取。

2、通过全局变量传递

顾名思义,就是借助一个全局变量做中转,去传递数据。还是以前面的两个 Activity 为例,传递不支持序列化的 Student 对象。我们可以先创建一个工具类,比如:

public class Transmitter {
public static Student student;
}

那么传递和接收时,就可以这么操作:

//传递
Student stu = new Student();
Transmitter.student = stu;
Intent intent = new Intent(this, Activity2);
startActivity(intent);
//接收
onCreate(…){
Student stu = Transmitter.student;
}

可以看到使用起来非常的方便快捷。

但是,全局变量在 APP 运行期间一直存在,如果通过全局变量存放的数据量比较大,变量个数多;并且在不需要使用后,没有及时的将全局变量置为 null,好让 GC 去回收,那么是有可能会引发 OOM 问题的。

因此,如果要使用全局变量来作为数据传递方法,那么就一定要注意维护好这些全局变量的状态。

3、通过 SharedPreferences 传递

SharedPreferences 是 Android 提供的一种实现数据存储的方式,它可以将数据以 xml 格式存储在机器中,通常用来存储 APP 的设置信息,我们也可以用它来实现 Activity 间的数据传递。

但是,SharedPreferences 因其特殊的工作方式,只提供了对部分基本类型和 String 的操作,对其它既有复杂类型和自定义类型是不支持的。它所支持的类型只有:

boolean
float
int
long
String
Set

仍旧拿前面的两个 Activity 煮栗子,要实现它们之间的数据传递,只需要现在 Activity1 中,将数据放入 SharedPreferences,如下:

SharedPreferences sp = getSharedPreferences(“FILENAME”, MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putBoolean(String key, boolean value);
editor.putFloat(String key, float value);
editor.putInt(String key, int value);
editor.putLong(String key, long value);
editor.putString(String key, String value);
editor.putStringSet(String key, Set values);
//editor.commit();
editor.apply();
startActivity(…);

然后在 Activity2 中通过 SharedPreferences 将数据取出来,如下:

SharedPreferences sp = getSharedPreferences(“FILENAME”, MODE_PRIVATE);
sp.getBoolean(String key, boolean defValue);
sp.getFloat(String key, float defValue);
sp.getInt(String key, int defValue);
sp.getLong(String key, long defValue);
sp.getString(String key, String defValue);
sp.getStringSet(String key, Set defValue);

关于 SharedPreferences 有几点需要注意:

**1、**getSharedPreferences(“FILENAME”, MODE_PRIVATE) 是通过 Context 调用的,发送和接收的 FILENAME、MODE_PRIVATE 都要一致。

2、发送时,往 SharedPreferences 存入数据后,需要提交,提交的方式有两种:commit、apply,这两个的区别如下:

**commit:**同步操作,立即将修改写到 Storage,有 boolean 类型返回值。

**apply:**立即刷新 In-memory 中的数据,然后启动异步任务将修改写到 Storage,无返回值。

当两个 apply 同时操作时,后调用 apply 的将会被保存到 Storage 中;当有 apply正在执行时,调用 commit,commit 将被阻塞,直到 apply 执行完。

因 Android framework 已经做好所有的事情,所以当我们不需要关注提交操作的返回值时,可以将 commit 无条件替换 apply 使用,而且 AS 也会建议将 commit 替换成 apply。

**3、**SharedPreferences 支持的数据类型都必须是支持序列化操作的,上面提到的 Set是一个 interface,我们并不能直接实例化,但我们可以使用它的直接或间接实现类,比如:HashSet、TreeSet、LinkedHashSet等等。

我们查看这几个的实现,不难发现,它们也都是实现了 Serializable 接口,支持序列化操作的:

public class HashSet
extends AbstractSet
implements Set, Cloneable, java.io.Serializable
public class TreeSet extends AbstractSet
implements NavigableSet, Cloneable, java.io.Serializable
public class LinkedHashSet
extends HashSet
implements Set, Cloneable, java.io.Serializable {

4、通过 SystemProperties 传递

这个类可以看做一个维护全局变量的类,只不过这里的全局变量是系统的,它们的值是 build.prop 文件里面的内容。我们先看一下它的定义:

/**

  • Gives access to the system properties store. The system properties
  • store contains a list of string key-value pairs.
  • {@hide}
    */
    public class SystemProperties

没错,这玩意是个 hide 的类,那就意味着正常情况下 SDK 里面是没有的,AS 里面也是访问不到的。不过我们还是可以通过一些手段去访问到它,比如反射、将源码的库导出到 AS 使用、将 APP 放在源码中编译等等。

这里我们就不关注用什么手段去访问它了,我们重点还是在利用它进行 Activity 之间的数据传递。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。

这里附上上述的面试题相关的几十套字节跳动,京东,小米,腾讯、头条、阿里、美团等公司21年的面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

由于篇幅有限,这里以图片的形式给大家展示一小部分。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 诸多细节。

由于篇幅有限,这里以图片的形式给大家展示一小部分。

[外链图片转存中…(img-Nu0gzxaM-1712498399073)]

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值