編輯:關於Android編程
在android中用intent傳遞數據是非常常見的操作,我們一般會用intent.putExtra()這個方法來放入自己要傳遞的數據,然後再另一個地方使用getxxx()來獲取,其中intent.putExtra()的傳參類型有很多種:
Intent putExtra(String name, String[] value) Intent putExtra(String name, Parcelable value) Intent putExtra(String name, long value) Intent putExtra(String name, boolean value) Intent putExtra(String name, double value) Intent putExtra(String name, Parcelable[] value) Intent putExtra(String name, char value) Intent putExtra(String name, int[] value) Intent putExtra(String name, int value) Intent putExtra(String name, double[] value) Intent putExtra(String name, short value) Intent putExtra(String name, long[] value) Intent putExtra(String name, boolean[] value) Intent putExtra(String name, short[] value) Intent putExtra(String name, String value) Intent putExtra(String name, Serializable value) Intent putExtra(String name, float[] value) Intent putExtra(String name, Bundle value) Intent putExtra(String name, byte[] value) Intent putExtra(String name, CharSequence value) Intent putExtra(String name, char[] value) Intent putExtra(String name, byte value) Intent putExtras(Intent src) Intent putExtras(Bundle extras)
可以看到其可以傳遞的包括基本數據類型(含基本數據類型的數組)、String(包含數組)、Parcelable(包含數組)、Serializable、Bundle、CharSequence、Intent幾種類型的數據。我們點進去看下具體實現:
public Intent putExtra(String name, String value) { if (mExtras == null) { mExtras = new Bundle(); } mExtras.putString(name, value); return this; }
public Intent putExtra(String name, int value) { if (mExtras == null) { mExtras = new Bundle(); } mExtras.putInt(name, value); return this; }
public Intent putExtra(String name, boolean value) { if (mExtras == null) { mExtras = new Bundle(); } mExtras.putBoolean(name, value); return this; }
我們點開了三個Intent putExtra(String name, String value),Intent putExtra(String name, int value),Intent putExtra(String name, boolean value)發現其實原理都一樣,他們都通過new Bundle.putxxx()來實現的,也就是說傳進來的這些數據都是通過Bundle這個容器來裝然後傳遞,在Intent類裡面維護了一個Bundle對象mExtras,如果intent已經攜帶了Bundle對象,那麼直接向裡面存儲數據,否則就新建一個Bundle對象, 點開 mExtras.putxxx()方法我們會發現,
public void putxxxx(@Nullable String key, value) {
unparcel();
mMap.put(key, value);
}
其實在BaseBundle裡面維護了一個ArrayMap
ArrayMap mMap = null;
我們intent的put操作和get操作就是對Bundle裡面的ArrayMap進行
mMap.put(key, value);和
mMap.get(key);操作,那Bundle到底是個什麼東東呢?我們要實現intent傳遞對象改怎麼做呢?Bundle我們可以看作是一個存儲可傳輸的數據的容器,什麼是可傳輸的呢?我的理解是像基本數據類型本身就可以直接轉換為字節流,所以是可傳輸的,還有就是實現實現序列化接口(String本身就實現了Serializable接口),在android中實現序列化接口有兩種方式
實現Serializable接口
實現Parcelable接口
其中實現Serializable接口在javase就已經支持,而Parcelable是Android特有的功能,效率比實現Serializable接口高。那他們有什麼區別?
作用
Serializable的作用是為了保存對象的屬性到本地文件、數據庫、網絡流、rmi以方便數據傳輸,當然這種傳輸可以是程序內的也可以是兩個程序間的。而Android的Parcelable的設計初衷是因為Serializable效率過慢,為了在程序內不同組件間以及不同Android程序間(AIDL)高效的傳輸數據而設計,這些數據僅在內存中存在,Parcelable是通過IBinder通信的消息的載體。
從上面的設計上我們就可以看出優劣了。
效率及選擇
Parcelable的性能比Serializable好,在內存開銷方面較小,所以在內存間數據傳輸時推薦使用Parcelable,如activity間傳輸數據,而Serializable可將數據持久化方便保存,所以在需要保存或網絡傳輸數據時選擇Serializable,因為android不同版本Parcelable可能不同,所以不推薦使用Parcelable進行數據持久化。
總結:所以在傳遞對象時對於需要傳遞的對象的序列化選擇可以加以區分,需要數據持久化的建議實現Serializable接口,只在內存間數據傳輸時推薦使用Parcelable。
編程實現
-實現Serializable接口
對於對於Serializable,類只需要實現Serializable接口,並提供一個序列化版本id(serialVersionUID)即可。,有人又會問了id(serialVersionUID)干啥的?
(Java的序列化機制是通過在運行時判斷類的serialVersionUID來驗證版本一致性的。在進行反序列化時,JVM會把傳來的字節流中的serialVersionUID與本地相應實體(類)的serialVersionUID進行比較,如果相同就認為是一致的,可以進行反序列化,否則就會出現序列化版本不一致的異常。添加serialVersionUID使得在序列化時保持版本的兼容性,即在版本升級時反序列化仍保持對象的唯一性。)
下面一個bean是實現Serializable接口的一個樣例:
/**
* =============================================================================
* Copyright (c) 2016 yuxin All rights reserved.
* Packname com.jju.yuxin.disanzhou
* Created by yuxin.
* Created time 2016/9/18 0018 下午 10:29.
* Version 1.0;
* Describe :
* History:
* ==============================================================================
*/
public class Person implements Serializable{
private static final long serialVersionUID = 1L;
private int id;
private String name;
public Person() {
}
public Person(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
intent數據的傳遞:
// 封裝數據
Person p = new Person();
p.setId(320840);
p.setName("小伙子");
Intent i = new Intent(MainActivity.this, FirstActivity.class);
i.putExtra("Person", p);
startActivity(i);
接收數據:
Person p = (Person)getIntent().getSerializableExtra("Person");
System.out.println("身份證"+p.getId());
System.out.println("姓名"+p.getName());
-實現Parcelable接口
實現Parcelable接口稍微復雜一些,但效率更高,下面是一個實現Parcelable接口的一個樣例:
CREATOR = new Parcelable.Creator() {
@Override
public Student createFromParcel(Parcel source) {
return new Student(source);
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
}
" data-snippet-id="ext.e80e81f253c4e7588321284c35d3907f" data-snippet-saved="false" data-codota-status="done">/**
* =============================================================================
* Copyright (c) 2016 yuxin All rights reserved.
* Packname com.jju.yuxin.disanzhou
* Created by yuxin.
* Created time 2016/9/18 0018 下午 9:47.
* Version 1.0;
* Describe :
* History:
* ==============================================================================
*/
public class Student implements Parcelable {
private int id;
private String name;
public Student() {
}
public Student(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeString(this.name);
}
protected Student(Parcel in) {
this.id = in.readInt();
this.name = in.readString();
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
@Override
public Student createFromParcel(Parcel source) {
return new Student(source);
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
}
intent數據的傳遞:
// 封裝數據
Student s = new Student();
s.setId(320840);
s.setName("小伙子");
Intent i = new Intent(MainActivity.this, FirstActivity.class);
i.putExtra("Student", s);
startActivity(i);
數據的接收:
Student s = (Student)getIntent().getParcelableExtra("Student");
System.out.println("學號:"+s.getId());
System.out.println("姓名:"+s.getName());
我們發現在實現Parcelable接口比較復雜在於要實現的幾個方法不清楚是什麼意思,我們來看下:
CREATOR = new Parcelable.Creator() {
@Override
public Student createFromParcel(Parcel source) {
return new Student(source);
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
}" data-snippet-id="ext.256f48df6af3727b54ec6212076d06e2" data-snippet-saved="false" data-codota-status="done"> @Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeString(this.name);
}
protected Student(Parcel in) {
this.id = in.readInt();
this.name = in.readString();
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
@Override
public Student createFromParcel(Parcel source) {
return new Student(source);
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
}
我們可以看到在方法中有很多個Parcel對象。這個類是用來封裝數據的容器,封裝後的數據可以通過Intent或IPC傳遞,除了基本類型外,只有實現了Parcelable接口的類才能放入parcel中,也就是說實現了Parcelable接口後可以把數據打包成Parcel對象對象來傳遞,並且只有實現了Parcelable接口的類才能放入parcel中,那實現了Parcelable接口的對象是如何打包和讀取的呢?我們會發現兩個方法
public void writeToParcel(Parcel dest, int flags);
這個方法就是傳入一個空的Parcel對象,然後將我們要存儲的對象的屬性寫進Parcel中去(注意寫入順序,因為在讀取是時要按照寫入順序來讀取)
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeString(this.name);
}
還有一個就是:
- public Student createFromParcel(Parcel source)
從方法名我們就可以看出他是從Parcel對象中獲取值來創建一個我們需要傳遞的的Student 對象
@Override
public Student createFromParcel(Parcel source) {
return new Student(source);
}
它這調用了Student的構造方法
protected Student(Parcel in) {
this.id = in.readInt();
this.name = in.readString();
}
也就是說對於對象傳遞時需要打包成Parcel對象傳遞,而打包和解包的過程都是我們自己來寫的。
題外話:對於實現Parcelable接口實現方法十分容易寫錯,如果你用android studio的話,安裝個*Android
Parcelable code generator*插件在你要實現Parcelable接口的bean上按住
alt+insert選擇Parcelable,就可以快速生成Parcelable代碼
總結上面所有intent的數據傳遞的重寫的方法,我們會發現都是將數據放入Bundle中然後傳遞的,那Bundle究竟是什麼呢?
Android手勢密碼LockPatternView、LockPasswordUtils、LockPatternUtils在使用別人寫的這個手勢密碼的時候,我們通常是有自
目前智能電視終端(智能電視和智能電視盒子)已經越來越火,過去主打視頻功能,如今的智能電視終端不僅會繼續完善視頻功能,還會加入電視游戲功能,同時這也趕上了“電視游戲機解禁”
Palette非常好用,也非常好玩。 Palette的作用是從圖像中提取突出的顏色,這樣我們可以根據提取到的色值把它賦給Toolbar,標題,狀態欄等,可以使我們的整個界
本節引言: 最近一段時間因為工作上的事以及面試等等,耽誤了博客的更新,這裡道歉下~ 今天下午去追夢網絡面試了一趟,全齊大神給小弟我上了一課,增長了