Android开发过程中,无法将对象的引用传给Activities或者Fragments,我们需要将这些对象放到一个Intent或者Bundle里面,然后再传递,这就需要用到序列化和反序列化。
- 序列化分类
- Parcelable原理
- Parcelable使用
- 回调接口传递
- 注意事项
序列化分类
(1)Serializable 是java的序列化技术,使用简单,频繁的IO操作,效率低
(2)Parcelable 是Android为我们提供的序列化的接口,使用稍微复杂,内存操作,效率高
(3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable在外界有变化的情况下不能很好的保证数据的持续性。尽管Serializable效率低点,但此时还是建议使用Serializable。存储到设备或者网络传输上选择Serializable。
Parcelable原理
(1)Parcelable是Android特有的序列化API,它的出现是为了解决Serializable在序列化的过程中消耗资源严重的问题,但是因为本身使用需要手动处理序列化和反序列化过程,会与具体的代码绑定,使用较为繁琐,一般只获取内存数据的时候使用。
Parcelable使用
1、首先创建一个ParcelBean对象,继承自Parcelable,这个就是我们要将其序列化的对象,对象里边的属性有数值、boolean、字符串、对象、数组和链表等各种类型,重点是看下各种类型的序列化和反序列化的方式。
import android.os.Parcel; import android.os.Parcelable; import java.util.ArrayList; import java.util.List; public class ParcelBean implements Parcelable{
public int count; public boolean flag; public String name; public ParcelItemBean itemBean; public List<ParcelItemBean> itmeList = new ArrayList<>(); public String[] array; //回调接口对象 public ParcelCallbackBean parcelCallbackBean; public ParcelBean() {
super(); } public ParcelBean(Parcel source) {
super(); count = source.readInt(); flag = source.readByte() != 0; name = source.readString(); itemBean= source.readParcelable(ParcelItemBean.class.getClassLoader()); // 读取对象需要提供一个类加载器去读取,因为写入的时候写入了类的相关信息 source.readTypedList(itmeList, ParcelItemBean.CREATOR); //对应writeTypeList array = source.createStringArray(); //回调接口 parcelCallbackBean= source.readParcelable(ParcelCallbackBean.class.getClassLoader()); } public static final Creator<ParcelBean> CREATOR = new Creator<ParcelBean>() {
@Override public ParcelBean createFromParcel(Parcel in) {
return new ParcelBean(in); } @Override public ParcelBean[] newArray(int size) {
return new ParcelBean[size]; } }; @Override public int describeContents() {
return 0; } @Override public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(count); dest.writeByte((byte) (flag ? 1 : 0)); dest.writeString(name); dest.writeParcelable(itemBean, flags); dest.writeTypedList(itmeList); dest.writeStringArray(array); //回调接口对象 dest.writeParcelable(parcelCallbackBean, flags); } }
2、里边有一个ParcelItemBean的子对象,如下
import android.os.Parcel; import android.os.Parcelable; public class ParcelItemBean implements Parcelable {
public String itemName; public ParcelItemBean(){
super(); } protected ParcelItemBean(Parcel in) {
super(); itemName = in.readString(); } public static final Creator<ParcelItemBean> CREATOR = new Creator<ParcelItemBean>() {
@Override public ParcelItemBean createFromParcel(Parcel in) {
return new ParcelItemBean(in); } @Override public ParcelItemBean[] newArray(int size) {
return new ParcelItemBean[size]; } }; @Override public int describeContents() {
return 0; } @Override public void writeToParcel(Parcel dest, int flags) {
dest.writeString(itemName); } }
3、对象序列化后需要通过Activity来加到ParcelableActivity的Intent中发送出去
import java.util.ArrayList; public class ParcelableActivity extends AppCompatActivity implements View.OnClickListener {
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_parcelable); initView(); } private void initView() {
findViewById(R.id.parcel).setOnClickListener(this); } @Override public void onClick(View v) {
switch (v.getId()) {
case R.id.parcel: parcelSend(); break; default: break; } } private void parcelSend() {
ParcelBean parcelBean = new ParcelBean(); parcelBean.name = "lisi"; parcelBean.flag = false; parcelBean.count = 66; //写入对象 ParcelItemBean parcelItemBean = new ParcelItemBean(); parcelItemBean.itemName = "itmeNNN"; parcelBean.itemBean = parcelItemBean; //写入list ParcelItemBean itemBean1 = new ParcelItemBean(); itemBean1.itemName = "item111"; ParcelItemBean itemBean2 = new ParcelItemBean(); itemBean2.itemName = "item222"; ArrayList<ParcelItemBean> beanList = new ArrayList<>(); beanList.add(itemBean1); beanList.add(itemBean2); parcelBean.itmeList = beanList; //写入数组 String array[] = new String[]{
"num1", "num2", "num3"}; parcelBean.array = array; //写入回调接口 ParcelCallbackListenerBinder.CallbackListener callbackListener = new ParcelCallbackListenerBinder.CallbackListener() {
@Override public void onComplete(Object obj) {
Log.d("parcel_call_back", "callBackComplete"); } @Override public void onError(String msg) {
Log.d("parcel_call_back", "callBackError"); } @Override public void onCancel() {
Log.d("parcel_call_back", "callBackCancel"); } }; ParcelCallbackListenerBinder.ClickCallbackListener clickCallbackListener = new ParcelCallbackListenerBinder.ClickCallbackListener() {
@Override public void onClick(String channel) {
Log.d("parcel_call_back", "clickCallBack"+channel); } }; ParcelCallbackBean parcelCallbackBean = new ParcelCallbackBean(new ParcelCallbackListenerBinder(callbackListener, clickCallbackListener)); parcelBean.parcelCallbackBean = parcelCallbackBean; Intent intent = new Intent(this, ParcelReceiveActivity.class); intent.putExtra("keyName", "zhangsan"); intent.putExtra("parcel", parcelBean); startActivity(intent); } }
4、上面是发送的Activity,还需要一个接收的ParcelReceiveActivity
public class ParcelReceiveActivity extends AppCompatActivity implements View.OnClickListener {
ParcelCallbackBean mParcelCallbackBean; @Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_parcel_receive); initView(); } private void initView() {
findViewById(R.id.click_callback).setOnClickListener(this); Intent intent = getIntent(); Log.d("ParcelReceiveActivity", "keyName = "+intent.getStringExtra("keyName")); ParcelBean parcelBean = intent.getParcelableExtra("parcel"); Log.d("ParcelReceiveActivity", "parcelBean.name = "+parcelBean.name); Log.d("ParcelReceiveActivity", "parcelBean.flag = "+parcelBean.flag); Log.d("ParcelReceiveActivity", "parcelBean.count = "+parcelBean.count); Log.d("ParcelReceiveActivity", "parcelBean.itemBean.itemName = "+parcelBean.itemBean.itemName); Log.d("ParcelReceiveActivity", "parcelBean.itmeList.get(0).itemName = "+parcelBean.itmeList.get(0).itemName); Log.d("ParcelReceiveActivity", "parcelBean.itmeList.get(1).itemName = "+parcelBean.itmeList.get(1).itemName); Log.d("ParcelReceiveActivity", "parcelBean.array[0] = "+parcelBean.array[0]); Log.d("ParcelReceiveActivity", "parcelBean.array[1] = "+parcelBean.array[1]); //获取传递过来的接口对象 mParcelCallbackBean = parcelBean.parcelCallbackBean; } @Override public void onClick(View v) {
switch (v.getId()) {
case R.id.click_callback: clickCallBack(); break; default: break; } } private void clickCallBack() {
mParcelCallbackBean.parcelCallbackListenerBinder.getClickCallbackListener().onClick("我是传递过来的点击事件"); } }
5、在接收的Activity里边打印Log,如下
ParcelReceiveActivity: keyName = zhangsan parcelBean.name = lisi parcelBean.flag = false parcelBean.count = 66 parcelBean.itemBean.itemName = itmeNNN parcelBean.itmeList.get(0).itemName = item111 parcelBean.itmeList.get(1).itemName = item222 parcelBean.array[0] = num1 parcelBean.array[1] = num2
回调接口传递
上面有一个回调接口的对象的传递,这里单独拿出来说一下,首先建立一个ParcelCallbackListenerBinder对象,继承自Binder,用来管理这两个回调接口
import android.os.Binder; public class ParcelCallbackListenerBinder extends Binder{
public CallbackListener callbackListener; public ClickCallbackListener clickCallbackListener; public ParcelCallbackListenerBinder(CallbackListener callbackListener, ClickCallbackListener clickCallbackListener) {
this.callbackListener = callbackListener; this.clickCallbackListener = clickCallbackListener; } public CallbackListener getCallbackListener() {
return callbackListener; } public ClickCallbackListener getClickCallbackListener() {
return clickCallbackListener; } public static interface CallbackListener {
void onComplete(Object obj); void onError(String msg); void onCancel(); } public static interface ClickCallbackListener {
void onClick(String channel); } }
然后再将这个封装的回调接口,封装到ParcelCallbackBean中,这个也是继承自Parcelable的
import android.os.Parcel; import android.os.Parcelable; import com.jd.test.phototest.activity.interfac.ParcelCallbackListenerBinder; public class ParcelCallbackBean implements Parcelable{
public ParcelCallbackListenerBinder parcelCallbackListenerBinder; public ParcelCallbackBean(ParcelCallbackListenerBinder binder) {
parcelCallbackListenerBinder = binder; } protected ParcelCallbackBean(Parcel source) {
Object object = source.readValue(ParcelCallbackListenerBinder.class.getClassLoader()); if (object instanceof ParcelCallbackListenerBinder) {
parcelCallbackListenerBinder = (ParcelCallbackListenerBinder) object; } } public static final Creator<ParcelCallbackBean> CREATOR = new Creator<ParcelCallbackBean>() {
@Override public ParcelCallbackBean createFromParcel(Parcel in) {
return new ParcelCallbackBean(in); } @Override public ParcelCallbackBean[] newArray(int size) {
return new ParcelCallbackBean[size]; } }; @Override public int describeContents() {
return 0; } @Override public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(parcelCallbackListenerBinder); } }
在ParcelReceiveActivity里进行回调,通过clickCallBack方法进行回调,在ParcelableActivity里进行回调的接收。我们来看一下点击回调的结果
parcel_call_back: clickCallBack我是传递过来的点击事件 parcel_call_back: clickCallBack我是传递过来的点击事件 parcel_call_back: clickCallBack我是传递过来的点击事件
注意事项
(1)Parcelable使用的时候要注意ParcelBean和writeToParcel也就是读写时各个属性的顺序,一定要一致,不然会存在问题。
(2)接口回调的ParcelCallbackListenerBinder类要继承自Binder,这个问啥我还没搞清楚,猜测应该和Parcelable底层使用的Binder进程通信有关,欢迎各位大佬指教。
尊重作者,尊重原创,参考文章:
https://www.jianshu.com/p/df35baa91541
https://blog.csdn.net/hacker_crazy/article/details/
https://www.cnblogs.com/tangZH/p/10998065.html
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/227983.html原文链接:https://javaforall.net
