Android编程权威指南总结

第一章    Android开发初体验

作为根元素, LinearLayout、RelativeLayout等等组件,必须指定Android XML资源文件的命名空间属性,这里是http://schemas.android.com/apk/res/android。

Android应用属于典型的事件驱动类型。不像命令行或脚本程序,事件驱动型应用启动后,即开始等待行为事件的发生,如用户点击某个按钮。

 
挑战一:在屏幕顶部弹出Toast
/**
 * 给Toast设置Gravity值, 
 * Gravity.TOP (顶部对齐) 和 Gravity.FILL_HORIZONTAL (宽度全屏)
 */
Toast t = Toast.makeText(MainActivity.this,R.string.toast_one,Toast.LENGTH_SHORT);
t.setGravity(Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 100);
t.show();

 

第二章    Android与MVC设计模式

一、MVC设计模式的简介

Android应用基于模型—视图—控制器(Model--View--Controller,MVC)的架构模式进行设计。MVC设计模式表明,应用的任何对象,归根结底都属于模型对象、视图对象和控制器对象中的一种。

  • 模型对象,存储着应用的数据和业务逻辑。模型类通常用来映射与应用相关的一些事物,比如:用户、商店里的商品、服务器上的图片或者一个电视节目。模型对象不关心用户界面,它为存储和管理数据而生。Android应用里,模型类通常就是我们创建的定制类。应用的全部模型对象组成了模型层。
  • 视图对象,知道如何在屏幕上绘制自己,以及如何响应用户的输入,如触摸动作等。一个简单的经验法则是:凡是能够在屏幕上看见的对象,就是视图对象。简单来讲就是在项目中创建的  layout.xml  布局文件。Android自带很多可配置的视图类,当然,也可以定制开发其他的视图类。应用的全部视图对象组成了视图层。
  • 控制器对象,含有应用的逻辑单元,是视图对象与模型对象联系的纽带。控制器对象响应视图对象触发的各种事件,此外还管理着模型层和视图层之间的数据流动、在Android的世界里,控制器通常是Activity、Fragment、Service等等的子类。

二、使用MVC设计模式的好处

随着应用功能的持续扩展,应用往往会变得过于复杂而难以理解。以Java类组织代码有助于从整体视角设计和理解应用。这样,我们就可以按类而不是按变量和方法思考设计开发问题。

同样,把Java类以模型层、视图层、控制器层进行分类组织,也有助于我们设计和理解Android应用。这样,我们就可以按层而非一个个类来考虑设计开发了。比如在视图层添加控件的时候,我们就可以不必考虑模型层的内容。

MVC设计模式还便于复用类。相比于功能多而全的类,功能单一的专用类更有利于代码的复用。

 


 

第三章     Activity的生命周期

一、点击回退键和Home键的区别

  • 单击设备的后退键,相当于告诉Android系统:“Activity已用完,现在不需要它了”。随即,系统就销毁了该Activity的视图及其内存里的相关信息。这实际是Android系统节约使用设备有限资源的一种方式。点击应用图标再次运行应用,Android创建了全新的Activity实例,重新走了onCreate()等一系列方法。
  • 单击主屏幕键,相当于告诉Android系统:“我去别处看看,稍后可能会回来”。此时,Android系统会先暂停,再停止当前的Activity。这表明Activity实例已处于停止状态(在内存中,但不可见,不会活动在前台)。这样,再次点击应用图标运行应用,Android系统就能快速响应,重启Activity,回到用户离开时的状态。这时候,系统不会调用onCreate()方法,而是直接onStart(),因为Activity实例还在内存里,自然不用重建了。但是需要注意的是:停止的Activity能够存在多久,谁也无法保证,系统需要回收内存时,它将首先销毁那些停止的Activity。

二、Activity的特殊暂停状态

Activity有时也会一直处于暂停状态(用户完全或部分可见,但是不在前台)。

  • 可能出现部分可见暂停状态的场景:在一个Activity之上启动带透明背景视图或小于屏幕尺寸视图的新Activity时。
  • 可能出现完全可见暂停状态的场景:应用多窗口模式下(Android 6.0及更高系统版本才支持),当前Activity在一个窗口完全可见,而用户在不包含当前Activity的另一个窗口操作时。

三、设备旋转

 1、简介

设备旋转时,系统会销毁当前Activity实例,然后再创建一个新的Activity实例。

旋转设备会改变设备配置。设备配置实际是一系列特征组合,用来描述设备当前状态。这些特征有:屏幕方向、屏幕像素密度、屏幕尺寸、键盘类型、底座模式以及语言等。通常,为匹配不同的设备配置,应用会提供不同的备选资源。比如:为适应不同的屏幕分辨率,在项目中添加多套图标等。

设备的屏幕像素密度是个固定的设备配置,无法在运行时发生改变,但是屏幕方向等特征可以在运行时发生改变。

在运行时,配置变更发生,可能会有更合适的资源来匹配新的设备配置。于是,Android销毁当前的Activity实例,为新配置寻找最佳资源,然后创建新实例使用这些资源。比如:如果你在 res 文件夹下创建一个水平模式布局,文件夹 layout_land,设备处于水平方向时,Android会找到并使用 res/layout_land 目录下的布局资源,其他情况下,会默认使用 res/layout 目录下的布局资源。

设备旋转时,Activity重新创建,一些变量也重置,这样可能会导致正在进行的操作回到最初状态,为了应对这个问题,一些不能改变的数据,就需要保存。

2、状态的保存

Activity本身提供了一个方法:protected void onSaveInstanceState(Bundle outState) ,该方法通常在onStop()方法之前调用,除非用户按了后退键(记住,按后退键就是告诉Android,当前Activity用完了,随后,该Activity就会完全从内存中被抹掉,自然,也就没有必要保存数据了)。

方法onSaveInstanceState(Bundle)的默认实现要求所有activity视图将自身状态数据保存在Bundle对象中。Bundle是存储字符串键与限定类型值之间映射关系(键_值对)的一种结构。可通过覆盖onSaveInstanceState(Bundle)方法,将一些数据保存在bundle中,然后在 onCreate(Bundle)方法中取回这些数据,比如:

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt("index",index);
    outState.putSerializable("question",mQuestion);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (savedInstanceState != null){
        index = savedInstanceState.getInt("index", 0);
        mQuestion = (Question) savedInstanceState.getSerializable("question");
    }
}

注意,在Bundle中存储和恢复的数据类型只能是基本类型primitive type)以及可以实现 Serializable或Parcelable接口的对象。在Bundle中保存定制类对象不是个好主意,因为你取回的对象可能已经没用了。比较好的做法是,通过其他方式保存定制类对象,而在Bundle中保存标识对象的基本类型数据。

 


 

四、再探Activity生命周期

1、activity的暂存状态

基于用户体验考虑,Android从不会为了回收内存而去销毁可见的activity。只有调用过onStop()并执行完成后,activity才会被标为可销毁。

系统随时会销毁掉已停止的activity,不用担心数据丢失,activity停止时,会调用onSaveInstanceState(Bundle)方法的。所以,解决旋转数据丢失问题,就是抢在系统销毁activity之前保存数据。调用该方法时,用户数据随即被保存在Bundle对象中,然后操作系统将Bundle对象放在activity记录中。

为了便于理解activity记录,我们增加一个暂存状态到activity的生命周期:

activity暂存后,activity对象不再存在,但操作系统会将activity记录对象保存起来,这样,在需要恢复activity时,操作系统可以使用暂存的activity记录重新激活activity。

注意,activity进入暂存状态并不一定需要调用onDestroy()方法,不过,onStop()和onSaveInstanceState(Bundle)是两个可靠的方法(除非设备出现重大故障),因而,常见的做法是:覆盖onSaveInstanceState(Bundle)方法,在Bundle对象中,保存当前activity的小的或暂存状态的数据;覆盖onStop()方法保存永久性的数据。

那么暂存的activity记录到底可以保留多久?用户按了后退键之后,系统会彻底销毁当前的activity,此时,暂存的activity记录同时被清除。此外,系统重启的话,暂存的activity记录也会被清除。

2、onSaveInstanceState(Bundle)方法相关

(1)onSaveInstanceState 的调用原则

覆盖onSaveInstanceState(Bundle)方法并不仅仅用于处理与设备旋转相关的问题,用户离开当前Activity用户界面,或Android需要回收内存时,activity也会被销毁。例如,用户按了主屏幕键,然后播放视频或玩游戏等等。

onSaveInstanceState(Bundle)在以下几种情况下会被执行:

  • 当用户按下Home键时。系统不知道你按下Home键要做什么,自然不知道该activity是否要销毁,所以系统会调用该方法,让用户有机会保存一些非永久性的数据。以下几种情况的分析都遵循该原则。
  • 长按Home键,选择运行其他程序时
  • 按下电源键关屏时
  • 从activity A中启动一个新的activity时
  • 屏幕方向旋转时

总而言之,onSaveInstanceState 的调用遵循一个重要原则:即当系统“未经你许可”时销毁了你的activity,则该方法会被系统调用,因为这是系统的责任,所以它必须给你提供一个可以保存数据的机会,至于要不要保存就随便你了。该方法调用将发生在onPause()或者onStop()方法之前。

(2)onSaveInstanceState 方法默认保存

如果我们没有覆写onSaveInstanceState 方法,此方法会默认保存activity中的某些状态数据,比如各种UI控件的状态。android应用框架中定义的几乎所有UI控件都恰当的实现了onSaveInstanceState()方法,因此当activity被摧毁和重建时,这些UI控件会自动保存和恢复状态数据。比如EditText控件会自动保存和恢复输入的数据,而CheckBox控件会自动保存和恢复选中状态。开发者只需要为这些控件指定一个唯一的ID(通过设置android:id属性即可), 剩余的事情就可以自动完成了。如果没有为控件指定ID, 则这个控件就不会进行自动的数据保存和恢复操作。

(3)是否需要重写onSaveInstanceState()方法

  既然该方法的默认实现可以自动的保存UI控件的状态数据, 那什么时候需要覆写该方法呢? 

  如果需要保存额外的数据时,,就需要覆写onSaveInstanceState()方法。大家需要注意的是:onSaveInstanceState()方法只适合保存瞬态数据,比如UI控件的状态、成员变量的值等,而不应该用来保存持久化数据,持久化数据应该当用户离开当前的 activity时,在 onPause() 或者onStop() 中保存(比如将数据保存到数据库或文件中)。说到这里,还要说一点的就是在onPause()或者onStop()中不适合用来保存比较费时的数据,所以这点要理解。若大量,则另开线程吧,别阻塞UI线程。

(4)另一个方法:onRestoreInstanceState()

onRestoreInstanceState()被调用的前提是,activity A“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity A,这种情况下activity A一般不会因为内存的原因被系统销毁,故activity A的onRestoreInstanceState方法不会被执行。此也说明onSaveInstanceState()和onRestoreInstanceState(),大多数情况下不成对被使用。

onRestoreInstanceState()在onStart() 和 onCreate(Bundle)之间调用。

 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值