Android開發小技巧積累
類安全轉換函數
在安卓開發中的類似如下類型轉換編輯器不會給出警告和try,catch提示,但是極易引起app崩潰。
String a = "1.333" ;
int b = Integer.valueOf(a) ;
以上代碼中如果a含有字符,或者小數就會引起崩潰,正確做法是在工具類中自己寫一個轉換函數,加入try,catch和默認值處理:
public final static int convertToInt(String value , int defaultValue){
if(value == null || "".equals(value.trim())){
return defaultValue ;
}
try{
return Integer.valueOf(value);
}catch (Exception e){
try{
return Double.valueOf(value).intValue() ;
}catch(Exception e1){
return defaultValue ;
}
}
}
使用時調用 :
int b = Utils.convertToInt(a,1) ;
安全地使用全局變量
public static的全局變量在內存不足時會被回收,所有要么用intent傳遞,要么保存在本地。intent傳遞的內容過多會增加工作量。 下面介紹一種保存在本地的方法。
我們的做法是每次修改全局變量的時候都把值序列化到本地文件中,使用的時候先檢查內存中的全局變量是否被回收,如果被回收就從本地 文件中再反序列化到內存中。
建議把所有全局變量都寫在一個類中,便于管理,即使寫在activity中也和activity本身沒有關系,因為全局變量是單獨保存的。
下面寫一個管理全局變量的類,保存用戶信息
public class GlobalVariables implements Serializable ,Cloneable {
private static final long serialVersionUID = 1L ;
private static GlobalVariables instance ;
public final static String TAG = "GlobalVariables" ;
private UserEntity user ;
private GlobalVariables(){}
public static GlobalVariables getInstance(){
if(instance == null ){
Object object = Utils.restoreObject(AppConstans.CACHEDIR + TAG) ;
if(object == null ){
object = new GlobalVariables() ;
Utils.saveObject(AppConstans.CACHEDIR + TAG,object) ;
}
instance = (GlobalVariables) object;
}
return instance ;
}
public UserEntity getUser(){
return user ;
}
public void setUser(UserEntity user){
this.user = user ;
Utils.saveObject(AppConstans.CACHEDIR + TAG,this) ;
}
public GlobalVariables readResolve() throws ObjectStreamException,CloneNotSupportedException{
instance = (GlobalVariables) this.clone();
return instance ;
}
private void readObject(ObjectInputStream ois) throws IOException,ClassNotFoundException{
ois.defaultReadObject();
}
public Object Clone() throws CloneNotSupportedException{
return super.clone() ;
}
public void reset(){
user = null ;
Utils.saveObject(AppConstans.CACHEDIR + TAG,this) ;
}
}</pre> <p>只能通過以下方式讀寫user數據:</p>
UserEntity user = GlobalVariables.getInstance().getUser() ;
GlobalVariables.getInstance().setUser(user);
GlobalVariables必須實現Serializable接口來支持序列化自身到本地。為了使一個單例類變成可序列化的,只實現Serializable接口還不夠。 因為一個序列化的對象在每次反序列化的時候,都會創建一個新的對象,而不僅僅是一個對原有對象的引用。為了防止這種情況,需要在單例類中加入 readResolve方法和readObject方法,并實現Cloneable接口。
在單例的構造方法中我們需要先判斷instance是否為空,不為空,證明全局變量沒有被回收,可以繼續使用;為空,要么是第一次啟動app,本地文件 不存在,要么是全局變量被回收了,于是我們需要從本地文件中將其還原回來。
我們在Utils類中編寫restoreObject和saveObject兩個方法,分別用于把全局變量序列化到本地,和從本地文件中反序列化到內存。代碼如下:
public static final void saveObject(String path , Object saveObject ){
FileOutputStream fos = null ;
ObjectOutputStream oos = null ;
File f = new File(path);
try{
fos = new FileOutputStream(f);
oos = new ObjectOutputStream(fos) ;
oos.writeObject(saveObject);
}catch(FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}finally {
try {
if(oos != null ){
oos.close();
}
if(fos != null ){
fos.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
public static final Object restoreObject(String path){
FileInputStream fis = null ;
ObjectInputStream ois = null ;
Object object = null ;
File f = new File(path) ;
if(!f.exists()){
return null ;
}
try{
fis = new FileInputStream(f) ;
ois = new ObjectInputStream(fis) ;
object = ois.readObject() ;
return object;
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}catch (ClassNotFoundException e){
e.printStackTrace();
}finally {
try{
if( ois != null){
ois.close();
}
if(fis !=null ){
fis.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
return object ;
}</pre> <p>對于全局變量中的自定義類型,例如我們的UserEntity,我們也要將這個實體聲明為可序列化的,它作為全局變量的一個屬性, 自身也必須實現Serializable接口。</p>
在app啟動的時候,我們要清空存儲在本地文件的全局變量,因為這些全局變量的生命周期都應該伴隨著app的關閉而消亡,但是我們 來不及在app關閉的時候做,所以只好在app啟動的時候第一件事就是清除這些臨時數據:
GlobalVariables.getInstance().reset();
本例中因為全局變量是用戶信息,是否要清理可以視情況而定,有的app是需要保存用戶信息到本地用于自動登錄的。其實除了用戶信息之外, 絕大部分的全局變量都是沒必要的,可以通過intent傳遞來代替的。
序列化的缺點:
1.每次設置全局變量的值都要強制執行一次序列化操作,容易造成ANR。本例中只有一個屬性,如果屬性多了,序列化次數也會變多,導致讀寫文件 次數變多,容易造成ANR。
2.序列化生成的文件,會因為內存不夠而丟失。因為序列化到內存目錄下后,由于內存空間有限,一旦內存空間耗盡,序列化文件就可能被清除, SharePreferences和SQLite數據庫也是儲存在內存空間上,所以這個文件如果太大,也會引發數據丟失問題。為什么不存在SD卡上?因為SD卡不穩定, 不是所有的手機ROM對其都有完好的支持。解決方案是每次使用完一個全局變量,就要將其清空,然后強制序列化到本地,以確保本地文件體積減小。
</div>
</code></code></code></code></code></code></code>