Android编程——自定义View类onSaveInstanceState与onRestoreInstanceState使用方法
在很多时候我们为获得在视图中自由绘制的能力, 需要创建一个继承于View类的定制类,然后重写onTouchEvent方法处理触摸时间,重写onDraw绘制自定义视觉效果。但这里可能会被一个问题困扰,那就是设备旋转导致数据丢失的问题,好在View类为我们提供了onSaveInstanceState和onRestoreInstanceState两个方法,虽然这两个方法和Activity两个方法很相似,但是千万别认为是一样的,因为他们的使用方法完全不同。
为了侧重数据保存的重点,我们这里简化了绘制的内容。下面定制的View子类功能是根据触摸事件发生的始末位置,绘制一组矩形。详细观察以下rectDrawingView定制类源码:
目前不需要研究上述代码,只要获得RectDrawingView即可。然后再布局文件中静态创建该组件。
现在我们来解释上述代码,首先如果我们要从XML布局文件创建RectDrawingView类那么就必须必须创建一个RectDrawingView(Context context, AttributeSet attrs)类,因为Android在实例XML文件中的组件时是通过调用上述构造方法实现的。然而,RectDrawingView(Context context)构造方法一般也需要添加,因为说不定某些时候我们就需要从代码中动态创建组件,所以为了统一情况,我们在自定义View子类时都会创建以上两个构造方法。
接下来在XML布局文件中声明RectDrawingView组件,需特别注意的是,android:id属性必须声明,如果没有为组件添加id,那么重写的onSaveInstanceState和onRestoreInstanceState方法是不会调用的。
关于onTouchEvent和onDraw方法这里不详细说了,很简单,如果需要请自行百度。现在主要集中在onSaveInstanceState和onRestoreInstanceState方法上,首先这两个方法与Activiy像似的两个方法最大的区别在于参数与返回值,View使用Parcelable传递数据,而Activity使用Bundle传递数据,很明显Bundle传递数据更为简单和强大,如果使用Parcelable对象传递自定义数据就需要实现Parcelable接口和CREATE静态常量,不但复杂而且代码量也很大。然而我们这里使用的RectF类作为基础数据,RectF是Android提供的并且已经实现了Parcelable接口和CREATE常量,这方便了许多。但是在onSaveInstanceState方法中,我们必须将父类保存的数据也保存在parcelable对象中,否则应用将发生崩溃。我了避免再次自定义Parcelable子类,因此我们这里使用Bundle将superData = super.onSaveInstanceState();父类保存数据和mRects自定义数据保存在其中,由于Bundle也是实现了Parcelable接口和CARETE常量的,因此在View的两个方法中传递是没有问题的。在onRestoreInstanceState方法中,我们需要将state强制转化成Bundle对象,如果为了安全一点,这里可以使用类型检查,然后将superData从Bundle对象中取出,再使用superData作为参数调用super.onRestoreInstanceState(superData);,相同的mRects也从Bundle中取出进行初始化,需要注意一点,这里千万不能将参数state传递给super.onRestoreInstanceState(state);方法,否则应用同样会崩溃。