Android

关注公众号 jb51net

关闭
首页 > 软件编程 > Android > Android Bundle传值

Android开发 Bundle传值的理解与使用小结

作者:阿俊学JAVA

这篇文章主要介绍了Android开发 Bundle传值的理解与使用小结,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧

什么是Bundle

Bundle经常出现在以下场合:

Activity状态数据的保存与恢复涉及到的两个回调:
void onSaveInstanceState (Bundle outState)
void onCreate (Bundle savedInstanceState)
Fragment的setArguments方法:void setArguments (Bundle args)
消息机制中的Message的setData方法:void setData (Bundle data)
...

Bundle从字面上解释为“一捆、一批、一包”,结合上述几个应用场合,可以知道Bundle是用来传递数据的。我们经常使用BundleActivity之间传递数据,传递的数据可以是booleanbyteintlongfloatdoublestring等基本类型或它们对应的数组也可以是对象或对象数组当Bundle传递的是对象或对象数组时,必须实现Serializable 或Parcelable接口。下面分别介绍Activity之间如何传递基本类型、传递对象:

Bundle的两个常用方法:

Bundle源码分析

Bundle的声明

public final class Bundle extends BaseBundle implements Cloneable, Parcelable:可以看出以下几点:

它使用final修饰,所以不可以被继承

它实现了两个接口,cloneable(复制)和Parcelable(打包),这就意味着他必须实现以下方法:

public Object clone()	//克隆数据
public int describeContents()	//写入数据
public void writeToParcel(Parcel parcel, int flags)	//将数据打包
public void readFromParcel(Parcel parcel)	//读取数据
public static final Parcelable.Creator<Bundle> CREATOR = new Parcelable.Creator<Bundle>()	//将打包的数据实例化

Bundle的内存结构

ArrayMap<String, Object> mMap = null;:使用的是ArrayMap,这个集合类存储的也是键值对,但是与Hashmap不同的是,hashmap采用的是“数组+链表”的方式存储,而Arraymap中使用的是两个数组进行存储,一个数组存储key,一个数组存储value,内部的增删改查都将会使用二分查找来进行,这个和SparseArray差不多,只不过sparseArraykey值只能是int类型的,而Arraymap可以是map型,所以在数据量不大的情况下可以使用这两个集合代替hashmap去优化性能

Get/Put解析

Bundle其实就是一个容器,内部使用了Arraymap去存储数据,那么就必然会提供getput方法,由于Bundle支持的数据类型太多,这里我们就举例布尔类型的,其他类型的方式都差不多:

getBoolean

public boolean getBoolean(String key, boolean defaultValue) {
    unparcel();
    Object o = mMap.get(key);
    if (o == null) {
        return defaultValue;
    }
    try {
        return (Boolean) o;
    } catch (ClassCastException e) {
        typeWarning(key, o, "Boolean", defaultValue, e);
        return defaultValue;
    }
}

数据读取的逻辑就是通过keyArrayMap里读出保存的数据,并转换成对应的类型返回,当没找到数据或发生类型转换异常时返回缺省值(default-value类似null的空值)putBoolean

public void putBoolean(@Nullable String key, boolean value) {
    unparcel();
    mMap.put(key, value);
}

unparcel()

先来看下BaseBundlemParcelledData的定义:

Parcel mParcelledData = null;

在大部分情况下mParcelledData都是null,因此unparcel()直接返回。当使用构造函数public Bundle(Bundle b)创建Bundle时,会给mParcelledData赋值;

oid copyInternal(BaseBundle from, boolean deep) {
    synchronized (from) {
        if (from.mParcelledData != null) {
            if (from.isEmptyParcel()) {
                mParcelledData = NoImagePreloadHolder.EMPTY_PARCEL;	//第一种取值
            } else {
                mParcelledData = Parcel.obtain();	//第二种取值
                mParcelledData.appendFrom(from.mParcelledData, 0, from.mParcelledData.dataSize());
                mParcelledData.setDataPosition(0);
            }
        } else {
            mParcelledData = null;	//第三种取值
        }
        if (from.mMap != null) {
            if (!deep) {
                mMap = new ArrayMap<>(from.mMap);
            } else {
                final ArrayMap<String, Object> fromMap = from.mMap;
                final int N = fromMap.size();
                mMap = new ArrayMap<>(N);
                for (int i = 0; i < N; i++) {
                    mMap.append(fromMap.keyAt(i), deepCopyValue(fromMap.valueAt(i)));
                }
            }
        } else {
            mMap = null;
        }
        mClassLoader = from.mClassLoader;
    }
}

从上述代码片段可以知道mParcelledData的取值有3种情况:

mParcelledData = EMPTY_PARCEL

mParcelledData = Parcel.obtain()

mParcelledData = null

总结

Bundle的使用

各种常用类型的Put/Get方法

Bundle提供了,用于读写基本类型的数据。Bundle操作基本数据类型的API表格如下所示:

传递基本类型的对象

数据打包

Bundle bundle = new Bundle();
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
//设置数据
String name = "zhangSan";
String num = "88888";
//把数据保存到Bundle里  
bundle.putString("name", name);
bundle.putString("num", num);
//把bundle放入intent里  
intent.putExtra("Message", bundle);
startActivity(intent);//开始打包

读取数据

Intent intent = getIntent();
//实例化一个Bundle  
Bundle bundle = intent.getExtras();
String name = bundle.getString("name");
String num = bundle.getString("num");

Activity通过Arguments给fragment类传值

Activity类动态加载fragment时可以通过fragmentsetArguments()传入值,并在fragment类中通过fragmentgetArguments()方法获得传入的值。

数据打包

Bundle bundle = new Bundle();
fragment01 fragment01 = new fragment01();//自定义的fragment类
//设置数据
String name = "zhangSan";
String num = "88888";
//把数据保存到Bundle里  
bundle.putString("name", name);
bundle.putString("num", num);
//把bundle通过Arguments放入要传值的fragment类里  
fragment01.setArguments(bundle);

读取数据

String name = getArguments().getString("name");
String num = getArguments().getString("num");

传递Serializable类型的对象

Serializable:是一个对象序列化的接口。一个类只有实现了Serializable接口,它的对象才是可序列化的。因此如果要序列化某些类的对象,这些类就必须实现Serializable接口。而实际上,Serializable是一个空接口,没有什么具体内容,它的目的只是简单的标识一个类的对象可以被序列化

打包数据

People people = new people();	//People类
//设置数据
String Name = "zhangSan";
String Num = "88888";
people.setName(Name);
people.setNum(Num);
//实例化一个Bundle  
Bundle bundle = new Bundle();
//把people数据放入到bundle中
bundle.putSerializable("people", people);
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
//把bundle放入intent里  
intent.putExtras(bundle);
startActivity(intent);//开始打包

读取数据

Intent intent = getIntent();
// 实例化一个Bundle  
Bundle bundle = intent.getExtras();
//获取里面的people里面的数据  
People people = (people) bundle.getSerializable("people");
String name = people.getName();
String num = people.getNum();

到此这篇关于Android开发 Bundle传值的理解与使用的文章就介绍到这了,更多相关Android Bundle传值内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文