在Activity间传递的数据通常比较简单,可是有时候实际开发中也会传一些比较复杂的数据,本节一块儿来学习更多Activity间数据的传递。java
在前面几节咱们只学习了一些经常使用类型的数据传递,主要是如下这些重载方法:android
putExtra(String name, boolean value)数组
putExtra(String name, byte value)微信
putExtra(String name, char value)数据结构
putExtra(String name, short value)架构
putExtra(String name, int value)app
putExtra(String name, long value)ide
putExtra(String name, float value)布局
putExtra(String name, double value)性能
putExtra(String name, String value)
putExtra(String name, CharSequence value)
putExtras(Intent src)
putExtras(Bundle extras)
putExtra(String name, Bundle value)
getBooleanExtra(String name, boolean defaultValue)
getByteExtra(String name, byte defaultValue)
getCharExtra(String name, char defaultValue)
getShortExtra(String name, short defaultValue)
getIntExtra(String name, int defaultValue)
getLongExtra(String name, long defaultValue)
getFloatExtra(String name, float defaultValue)
getDoubleExtra(String name, double defaultValue)
getStringExtra(String name)
getCharSequenceExtra(String name)
getExtras()
getBundleExtra(String name)
能够发现主要包括boolean、byte、char、short、int、long、float、double、String、CharSequence几个,固然也能够先将数据打包为Bundle或Intent对象再传递。
然而在实际开发中常常会碰见以上经常使用类型的数组或列表的组合型数据,其实也很是简单。
认真的同窗可能已经发现了,每个基本数据类型都有对应数组数据的重载方法,分别以下:
putExtra(String name, boolean[] value)
putExtra(String name, byte[] value)
putExtra(String name, short[] value)
putExtra(String name, char[] value)
putExtra(String name, int[] value)
putExtra(String name, long[] value)
putExtra(String name, float[] value)
putExtra(String name, double[] value)
putExtra(String name, String[] value)
putExtra(String name, CharSequence[] value)
getBooleanArrayExtra(String name)
getByteArrayExtra(String name)
getShortArrayExtra(String name)
getCharArrayExtra(String name)
getIntArrayExtra(String name)
getLongArrayExtra(String name)
getFloatArrayExtra(String name)
getDoubleArrayExtra(String name)
getStringArrayExtra(String name)
getCharSequenceArrayExtra(String name)
putExtra()方法的参数简单替换为数组类型的便可,而后使用数组的专用方法获取,使用起来也很是简单。
在传递列表型数据的时候稍微有一些不一样了,Intent还提供了如下这几个重载方法:
putIntegerArrayListExtra(String name, ArrayList<Integer> value)
putStringArrayListExtra(String name, ArrayList<String> value)
putCharSequenceArrayListExtra(String name, ArrayList<CharSequence> value)
getIntegerArrayListExtra(String name)
getStringArrayListExtra(String name)
getCharSequenceArrayListExtra(String name)
从以上几个方法能够知道,Intent自带传递Integer、String、CharSequence三种类型的列表数据,若是须要传递到额数据是这几种类型,或可以转换为这几种类型,那么数据的传递也变得很顺利了。
前面学习的几个方法使用起来仍是比较简单的,可是会发现一个问题,以上学习的方法没法传输对象(如图片)、对象的数组或集合,那就须要用到如下这些方法了。
intent还有如下这些重载方法:
putExtra(String name, Serializable value)
putExtra(String name, Parcelable value)
putExtra(String name, Parcelable[] value)
putParcelableArrayListExtra(String name, ArrayList<? extends Parcelable> value)
getSerializableExtra(String name)
getParcelableExtra(String name)
getParcelableArrayExtra(String name)
getParcelableArrayListExtra(String name)
可能你已经发现了,这里提到的Serializable类型和Parcelable类型数据究竟是什么呢?接下来分别来学习。
Serializable接口是启用其序列化功能的接口,实现java.io.Serializable 接口的类是可序列化的,没有实现此接口的类将不能使它们的任一状态被序列化或逆序列化(若是不懂序列化,建议复习巩固Java部分的序列化知识模块)。
Serializable实现序列化的方法也很简单,将须要序列化的类实现Serializable接口,Serializable接口中没有任何方法,只需在类中指定serialVersionUID的值,该值能够任意指定一个值。能够理解为一个标记,即代表这个类能够序列化。
假如须要使用Intent传递一个Person对象,就先要将其序列化,以下示例代码:
package com.jinyu.cqkxzsxy.android.activity.equipmentupdate.entity; import java.io.Serializable; /** * @建立者 鑫鱻 * @描述 Android零基础入门到精通系列教程 * 首发微信公众号分享达人秀(ShareExpert) */ public class Person implements Serializable { private static final long serialVersionUID = 1L; // 序列化ID private String name; // 姓名 private int age; // 年龄 public Person() { this.name = "未知"; this.age = 18; } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
而后便可调用前面的put和get方法来传递复杂对象数据了。
因为Serializable在序列化的时候会产生大量的临时变量,从而引发频繁的GC,会影响持续性能。在使用内存的时候,Parcelable比Serializable性能高,因此推荐使用Parcelable。
实现Parcelable接口稍微复杂一些,但效率更高,推荐用这种方法提升性能。实现步骤以下:
将须要序列化的类实现Parcelable接口。
重写writeToParcel方法,将对象序列化为一个Parcel对象。
重写describeContents方法,描述内容接口,默认返回0。实例化静态内部对象CREATOR实现接口Parcelable.Creator。其中public static final一个都不能少,内部对象CREATOR的名称也不能改变,必须所有大写。需重写本接口中的两个方法:
createFromParcel(Parcel in) 实现从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层。
newArray(int size) 建立一个类型为T,长度为size的数组,仅一句话便可(return new T[size]),供外部类反序列化本类数组使用。
接下来将上面的Person类进行改造,代码以下:
package com.jinyu.cqkxzsxy.android.activity.equipmentupdate.entity; import android.os.Parcel; import android.os.Parcelable; /** * @建立者 鑫鱻 * @描述 Android零基础入门到精通系列教程 * 首发微信公众号分享达人秀(ShareExpert) */ public class Person implements Parcelable { private String name; // 姓名 private int age; // 年 protected Person(Parcel in) { // 在读取Parcel容器里的数据时,必须按成员变量声明的顺序读取数据,否则会出现获取数据出错 name = in.readString(); age = in.readInt(); } public static final Creator<Person> CREATOR = new Creator<Person>() { // 再经过createFromParcel将Parcel对象映射成原对象 @Override public Person createFromParcel(Parcel in) { return new Person(in); } // 供外部类反序列化本类数组使用 @Override public Person[] newArray(int size) { return new Person[size]; } }; // 内容接口描述,默认返回0便可 @Override public int describeContents() { return 0; } // 按照声明顺序打包数据到Parcel对象中,既将数据打包到Parcel容器中 @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); dest.writeInt(age); } public Person() { this.name = "未知"; this.age = 18; } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
而后便可调用前面的put和get方法来传递复杂对象数据了,固然也能够是对象的数组或列表型数据。
在使用中须要注意的是,Parcelable不能使用在要将数据存储在磁盘上的状况,由于Parcelable不能很好的保证数据的持续性在外界有变化的状况下。尽管Serializable效率低点,但此时仍是建议使用Serializable。
若是须要将一个对象在多个Activity之间传递,或者要连续传递好几层,这种状况下若是使用以上方法就须要重复屡次,使用起来就特别别扭,这种状况就能够考虑使用全局Application。
Android系统在每一个程序运行的时候都会建立一个Application对象,并且只会建立一个,因此Application 是单例(singleton)模式的一个类,并且Application对象的生命周期是整个程序中最长的,他的生命周期等于这个程序的生命周期。若是想存储一些值,使用 Application就须要自定义类实现Application类,而后在AndroidManifest.xml中使用咱们自定义的Application 而非系统默认的。
这里简单使用一个示例来学习,这里简化为全局保存一个状态值,能够方便在各Activity中进行传递。首先自定义Application类,代码以下:
package com.jinyu.cqkxzsxy.android.activity.equipmentupdate; import android.app.Application; /** * @建立者 鑫鱻 * @描述 Android零基础入门到精通系列教程 * 首发微信公众号分享达人秀(ShareExpert) */ public class MyApplication extends Application { private int state; public int getState() { return state; } public void setState(int state) { this.state = state; } }
而后在AndroidManifest.xml中声明,为application标签添加android:name属性,代码以下:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jinyu.cqkxzsxy.android.activity.equipmentupdate"> <application android:name=".MyApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
最后在须要使用定义的全局变量的地方便可调用,核心代码以下:
package com.jinyu.cqkxzsxy.android.activity.equipmentupdate; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; public class TestActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_shop); // ... MyApplication app = (MyApplication) getApplicationContext(); // 保存数据 app.setState(1); // ... // 读取数据 int state = app.getState(); // ... } }
这样就很是方便的在各Activity之间进行数据传递了。若是想要在整个应用程序中任何位置都能使用,能够对MyApplication类进行适当的改造,这里不作过多说明。
可是须要注意的是,当因为某些缘由(好比系统内存不足),咱们的app会被系统强制杀死,此时再次点击进入应用时,系统会直接进入被杀死前的那个界面,制造一种历来没有被杀死的假象。那么问题来了,系统强制中止了应用,进程死了,那么再次启动时Application天然新的,那里边的数据天然木有啦,若是直接使用极可能报空指针或者其余错误。
因此在使用时必定要作好非空判断,若是数据为空能够考虑逻辑上让应用直接返回到最初的Activity。
上面的Application就是基于单例的,单例模式的特色就是能够保证系统中一个类有且只有一个实例。
这里作一个简单的示例,如定义一个数据持有者类,代码以下:
package com.jinyu.cqkxzsxy.android.activity.equipmentupdate.entity; /** * @建立者 鑫鱻 * @描述 Android零基础入门到精通系列教程 * 首发微信公众号分享达人秀(ShareExpert) */ public class DataHolder { private String data; public String getData() { return data; } public void setData(String data) { this.data = data; } private static final DataHolder holder = new DataHolder(); public static DataHolder getInstance() { return holder; } }
而后在使用的地方便可直接调用,以下所示:
// 更新数据
DataHolder.getInstance().setData(data);
// 获取数据
Stringdata=DataHolder.getInstance().getData();
这样使用起来也很是简单。
这个能够直接在Activity中完成单独一个数据结构,和单例差很少。
这里将上面的单例模式类简单修改,代码以下:
package com.jinyu.cqkxzsxy.android.activity.equipmentupdate.entity; /** * @建立者 鑫鱻 * @描述 Android零基础入门到精通系列教程 * 首发微信公众号分享达人秀(ShareExpert) */ public class DataHolder { private static String data; public static String getData() { return data; } public static void setData(String strData) { data = strData; } }
这样就能够在启动Activity以前设置数据,新的Activity中获取数据。
// 更新数据
DataHolder.setData(data);
// 获取数据
Stringdata=DataHolder.getData();
须要注意的是,若是数据很大不少(如bitmap),处理不当是很容易致使内存泄露或者内存溢出的,能够考虑使用WeakReferences 将数据包装起来。
除了以上介绍的几种方式,还可使用持久化数据等方法,这里先不作过多介绍,在后续的学习中会陆续接触到。
今天就先到这里,若是有问题欢迎留言一块儿探讨,也欢迎加入Android零基础入门技术讨论微信群,共同成长!
若是该系列分享对你有帮助,就动动手指关注、点赞、留言吧,你的互动就是对我最大的鼓励!
此文章版权为微信公众号分享达人秀(ShareExpert)——鑫鱻全部,若需转载请联系做者受权,特此声明!
往期总结回顾:
Android零基础入门第1节:Android的前世此生
Android零基础入门第2节:Android 系统架构和应用组件那些事
Android零基础入门第3节:带你一块儿来聊一聊Android开发环境
Android零基础入门第4节:正确安装和配置JDK, 高富帅养成第一招
Android零基础入门第5节:善用ADT Bundle, 轻松邂逅女神
Android零基础入门第6节:配置优化SDK Manager, 正式约会女神
Android零基础入门第7节:搞定Android模拟器,开启甜蜜之旅
Android零基础入门第8节:HelloWorld,个人第一趟旅程出发点
Android零基础入门第9节:Android应用实战,不懂代码也能够开发
Android零基础入门第10节:开发IDE大升级,终于迎来了Android Studio
Android零基础入门第11节:简单几步带你飞,运行Android Studio工程
Android零基础入门第12节:熟悉Android Studio界面,开始装逼卖萌
Android零基础入门第13节:Android Studio个性化配置,打造开发利器
Android零基础入门第14节:使用高速Genymotion,跨入火箭时代
Android零基础入门第15节:掌握Android Studio项目结构,扬帆起航
Android零基础入门第16节:Android用户界面开发概述
Android零基础入门第17节:文本框TextView
Android零基础入门第18节:输入框EditText
Android零基础入门第19节:按钮Button
Android零基础入门第20节:复选框CheckBox和单选按钮RadioButton
Android零基础入门第21节:开关组件ToggleButton和Switch
Android零基础入门第22节:图像视图ImageView
Android零基础入门第23节:图像按钮ImageButton和缩放按钮ZoomButton
Android零基础入门第24节:自定义View简单使用,打造属于你的控件
Android零基础入门第25节:简单且最经常使用的LinearLayout线性布局
Android零基础入门第26节:两种对齐方式,layout_gravity和gravity大不一样
Android零基础入门第27节:正确使用padding和margin
Android零基础入门第28节:轻松掌握RelativeLayout相对布局
Android零基础入门第29节:善用TableLayout表格布局
Android零基础入门第30节:两分钟掌握FrameLayout帧布局
Android零基础入门第31节:少用的AbsoluteLayout绝对布局
Android零基础入门第32节:新推出的GridLayout网格布局
Android零基础入门第33节:Android事件处理概述
Android零基础入门第34节:Android中基于监听的事件处理
Android零基础入门第35节:Android中基于回调的事件处理
Android零基础入门第36节:Android系统事件的处理
Android零基础入门第37节:初识ListView
Android零基础入门第38节:初识Adapter
Android零基础入门第39节:ListActivity和自定义列表项
Android零基础入门第40节:自定义ArrayAdapter
Android零基础入门第41节:使用SimpleAdapter
Android零基础入门第42节:自定义BaseAdapter
Android零基础入门第43节:ListView优化和列表首尾使用
Android零基础入门第44节:ListView数据动态更新
Android零基础入门第45节:网格视图GridView
Android零基础入门第46节:列表选项框Spinner
Android零基础入门第47节:自动完成文本框AutoCompleteTextView
Android零基础入门第48节:可折叠列表ExpandableListView
Android零基础入门第49节:AdapterViewFlipper图片轮播
Android零基础入门第50节:StackView卡片堆叠
Android零基础入门第51节:进度条ProgressBar
Android零基础入门第52节:自定义ProgressBar炫酷进度条
Android零基础入门第53节:拖动条SeekBar和星级评分条RatingBar
Android零基础入门第54节:视图切换组件ViewSwitcher
Android零基础入门第55节:ImageSwitcher和TextSwitcher
Android零基础入门第56节:翻转视图ViewFlipper
Android零基础入门第57节:DatePicker和TimePicker选择器
Android零基础入门第58节:数值选择器NumberPicker
Android零基础入门第59节:经常使用三大Clock时钟组件
Android零基础入门第60节:日历视图CalendarView和定时器Chronometer
Android零基础入门第61节:滚动视图ScrollView
Android零基础入门第62节:搜索框组件SearchView
Android零基础入门第63节:值得借鉴学习的选项卡TabHost
Android零基础入门第64节:揭开RecyclerView庐山真面目
Android零基础入门第65节:RecyclerView分割线开发技巧
Android零基础入门第66节:RecyclerView点击事件处理
Android零基础入门第67节:RecyclerView数据动态更新
Android零基础入门第68节:RecyclerView添加首尾视图
Android零基础入门第69节:ViewPager快速实现引导页
Android零基础入门第70节:ViewPager打造TabHost效果
Android零基础入门第71节:CardView简单实现卡片式布局
Android零基础入门第72节:SwipeRefreshLayout下拉刷新
Android零基础入门第73节:Activity建立和配置
Android零基础入门第74节:Activity启动和关闭
Android零基础入门第75节:Activity状态和生命周期
Android零基础入门第76节:Activity数据保存和横竖屏切换
Android零基础入门第77节:Activity任务栈和启动模式
Android零基础入门第78节:四大组件的纽带——Intent
Android零基础入门第79节:Intent 属性详解(上)
Android零基础入门第80节:Intent 属性详解(下)
Android零基础入门第81节:Activity数据传递
Android零基础入门第82节:Activity数据回传