分享

Android开发小技巧积累

 scxingm 2015-12-21

类安全转换函数


在安卓开发中的类似如下类型转换编辑器不会给出警告和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) ;}}


只能通过以下方式读写user数据:


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 ;}


对于全局变量中的自定义类型,例如我们的UserEntity,我们也要将这个实体声明为可序列化的,它作为全局变量的一个属性, 自身也必须实现Serializable接口。


在app启动的时候,我们要清空存储在本地文件的全局变量,因为这些全局变量的生命周期都应该伴随着app的关闭而消亡,但是我们 来不及在app关闭的时候做,所以只好在app启动的时候第一件事就是清除这些临时数据:


GlobalVariables.getInstance().reset();


本例中因为全局变量是用户信息,是否要清理可以视情况而定,有的app是需要保存用户信息到本地用于自动登录的。其实除了用户信息之外, 绝大部分的全局变量都是没必要的,可以通过intent传递来代替的。


序列化的缺点:


  1. 每次设置全局变量的值都要强制执行一次序列化操作,容易造成ANR。本例中只有一个属性,如果属性多了,序列化次数也会变多,导致读写文件 次数变多,容易造成ANR。

  2. 序列化生成的文件,会因为内存不够而丢失。因为序列化到内存目录下后,由于内存空间有限,一旦内存空间耗尽,序列化文件就可能被清除,SharePreferences和SQLite数据库也是储存在内存空间上,所以这个文件如果太大,也会引发数据丢失问题。为什么不存在SD卡上?因为SD卡不稳定,不是所有的手机ROM对其都有完好的支持。解决方案是每次使用完一个全局变量,就要将其清空,然后强制序列化到本地,以确保本地文件体积减小。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多