[小而美]Android开发小技巧积累

首发:Android开发小技巧积累

类安全转换函数

在安卓开发中的类似如下类型转换编辑器不会给出警告和try,catch提示,但是极易引起app崩溃。

[代码]java代码:


1

2

String a = "1.333" ;

int b = Integer.valueOf(a) ;


以上代码中如果a含有字符,或者小数就会引起崩溃,正确做法是在工具类中自己写一个转换函数,加入try,catch和默认值处理:

[代码]java代码:


01

02

03

04

05

06

07

08

09

10

11

12

13

14

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 ;

           }

       }

   }


使用时调用 :

[代码]java代码:

1

int b = Utils.convertToInt(a,1) ;


安全地使用全局变量

public static的全局变量在内存不足时会被回收,所有要么用intent传递,要么保存在本地。intent传递的内容过多会增加工作量。 下面介绍一种保存在本地的方法。

我们的做法是每次修改全局变量的时候都把值序列化到本地文件中,使用的时候先检查内存中的全局变量是否被回收,如果被回收就从本地 文件中再反序列化到内存中。

建议把所有全局变量都写在一个类中,便于管理,即使写在activity中也和activity本身没有关系,因为全局变量是单独保存的。

下面写一个管理全局变量的类,保存用户信息

[代码]java代码:


01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

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数据:

[代码]java代码:


1

2

UserEntity user = GlobalVariables.getInstance().getUser() ;

GlobalVariables.getInstance().setUser(user);


GlobalVariables必须实现Serializable接口来支持序列化自身到本地。为了使一个单例类变成可序列化的,只实现Serializable接口还不够。 因为一个序列化的对象在每次反序列化的时候,都会创建一个新的对象,而不仅仅是一个对原有对象的引用。为了防止这种情况,需要在单例类中加入 readResolve方法和readObject方法,并实现Cloneable接口。

在单例的构造方法中我们需要先判断instance是否为空,不为空,证明全局变量没有被回收,可以继续使用;为空,要么是第一次启动app,本地文件 不存在,要么是全局变量被回收了,于是我们需要从本地文件中将其还原回来。

我们在Utils类中编写restoreObject和saveObject两个方法,分别用于把全局变量序列化到本地,和从本地文件中反序列化到内存。代码如下:

[代码]java代码:


01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

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启动的时候第一件事就是清除这些临时数据:

[代码]java代码:


1

GlobalVariables.getInstance().reset();


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

序列化的缺点:

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

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

bringToFront可以调整布局层次

Android中的ViewGroup是通过一个Array来保存其Children,当调用某个childView的bringToFront时, 是将该childView放在其Parent的Array数组的最后,ViewGroup的dispatchDraw在draw时是按照Array从前往后依次调用drawChild的, 这样最后一个childView就在最前面了。


关于Java和Android大牛频道

Java和Android大牛频道是一个数万人关注的探讨Java和Android开发的公众号,分享和原创最有价值的干货文章,让你成为这方面的大牛!

我们探讨android和Java开发最前沿的技术:android性能优化 ,插件化,跨平台,动态化,加固和反破解等,也讨论设计模式/软件架构等。由群来自BAT的工程师组成的团队

关注即送红包,回复:“百度” 、“阿里”、“腾讯” 有惊喜!!!关注后可用入微信群。群里都是来自百度阿里腾讯的大牛。

欢迎关注我们,一起讨论技术,扫描和长按下方的二维码可快速关注我们。搜索微信公众号:JANiubility。


公众号:JANiubility


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值