Android開發(fā)過程中谤祖,無法將對(duì)象的引用傳給Activities或者Fragments油宜,我們需要將這些對(duì)象放到一個(gè)Intent或者Bundle里面昂勉,然后再傳遞敲街,這就需要用到序列化和反序列化。
- 序列化分類
- Parcelable原理
- Parcelable使用
- 回調(diào)接口傳遞
- 注意事項(xiàng)
序列化分類
(1)Serializable 是java的序列化技術(shù),使用簡(jiǎn)單摆尝,頻繁的IO操作温艇,效率低
(2)Parcelable 是Android為我們提供的序列化的接口,使用稍微復(fù)雜堕汞,內(nèi)存操作勺爱,效率高
(3)Parcelable不能使用在要將數(shù)據(jù)存儲(chǔ)在磁盤上的情況,因?yàn)镻arcelable在外界有變化的情況下不能很好的保證數(shù)據(jù)的持續(xù)性讯检。盡管Serializable效率低點(diǎn)琐鲁,但此時(shí)還是建議使用Serializable。存儲(chǔ)到設(shè)備或者網(wǎng)絡(luò)傳輸上選擇Serializable人灼。
Parcelable原理
(1)Parcelable是Android特有的序列化API围段,它的出現(xiàn)是為了解決Serializable在序列化的過程中消耗資源嚴(yán)重的問題,但是因?yàn)楸旧硎褂眯枰謩?dòng)處理序列化和反序列化過程投放,會(huì)與具體的代碼綁定奈泪,使用較為繁瑣,一般只獲取內(nèi)存數(shù)據(jù)的時(shí)候使用灸芳。
(2)Parcelable依賴于Parcel段磨,Parcel的意思是包裝,實(shí)現(xiàn)原理是在內(nèi)存中建立一塊共享數(shù)據(jù)塊耗绿,序列化和反序列化均是操作這一塊的數(shù)據(jù)苹支,如此來實(shí)現(xiàn)。
Parcelable使用
1误阻、首先創(chuàng)建一個(gè)ParcelBean對(duì)象债蜜,繼承自Parcelable,這個(gè)就是我們要將其序列化的對(duì)象究反,對(duì)象里邊的屬性有數(shù)值寻定、boolean、字符串精耐、對(duì)象狼速、數(shù)組和鏈表等各種類型,重點(diǎn)是看下各種類型的序列化和反序列化的方式卦停。
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;
//回調(diào)接口對(duì)象
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()); // 讀取對(duì)象需要提供一個(gè)類加載器去讀取,因?yàn)閷懭氲臅r(shí)候?qū)懭肓祟惖南嚓P(guān)信息
source.readTypedList(itmeList, ParcelItemBean.CREATOR); //對(duì)應(yīng)writeTypeList
array = source.createStringArray();
//回調(diào)接口
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);
//回調(diào)接口對(duì)象
dest.writeParcelable(parcelCallbackBean, flags);
}
}
2向胡、里邊有一個(gè)ParcelItemBean的子對(duì)象,如下
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惊完、對(duì)象序列化后需要通過Activity來加到ParcelableActivity的Intent中發(fā)送出去
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;
//寫入對(duì)象
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;
//寫入數(shù)組
String array[] = new String[]{"num1", "num2", "num3"};
parcelBean.array = array;
//寫入回調(diào)接口
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僵芹、上面是發(fā)送的Activity,還需要一個(gè)接收的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]);
//獲取傳遞過來的接口對(duì)象
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("我是傳遞過來的點(diǎn)擊事件");
}
}
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
回調(diào)接口傳遞
上面有一個(gè)回調(diào)接口的對(duì)象的傳遞,這里單獨(dú)拿出來說一下,首先建立一個(gè)ParcelCallbackListenerBinder對(duì)象件豌,繼承自Binder疮方,用來管理這兩個(gè)回調(diào)接口
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);
}
}
然后再將這個(gè)封裝的回調(diào)接口,封裝到ParcelCallbackBean中茧彤,這個(gè)也是繼承自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里進(jìn)行回調(diào)骡显,通過clickCallBack方法進(jìn)行回調(diào),在ParcelableActivity里進(jìn)行回調(diào)的接收棘街。我們來看一下點(diǎn)擊回調(diào)的結(jié)果
parcel_call_back: clickCallBack我是傳遞過來的點(diǎn)擊事件
parcel_call_back: clickCallBack我是傳遞過來的點(diǎn)擊事件
parcel_call_back: clickCallBack我是傳遞過來的點(diǎn)擊事件
注意事項(xiàng)
(1)Parcelable使用的時(shí)候要注意ParcelBean和writeToParcel也就是讀寫時(shí)各個(gè)屬性的順序蟆盐,一定要一致承边,不然會(huì)存在問題遭殉。
(2)接口回調(diào)的ParcelCallbackListenerBinder類要繼承自Binder,這個(gè)問啥我還沒搞清楚博助,猜測(cè)應(yīng)該和Parcelable底層使用的Binder進(jìn)程通信有關(guān)险污,歡迎各位大佬指教。
尊重作者富岳,尊重原創(chuàng)蛔糯,參考文章:
http://www.reibang.com/p/df35baa91541
https://blog.csdn.net/hacker_crazy/article/details/80840868
https://www.cnblogs.com/tangZH/p/10998065.html