【转】 Pro Android学习笔记(五六):配置变化
横屏竖屏的切换就是最为常见的配置变化,我们在Pro Android学习笔记(四一):Fragment(6):数据保留中讨论过。 配置变化还有设备连接了dock,改变语言等,在资源res/中,不同的配置有不同的后缀来进行最佳匹配,具体见Pro Android学习笔记(四):了解Android资源(下)的资源和配置的变更 ,我们从中可以看到Android检测哪些配置变化。
当配置变化时,当前的activity被destroy,并新re-created一个activity对象,我们要确保用户体验的无缝切换。我们应该尽量避免re-create的时间,减少activity处理的非UI部分。在配置变化是activity被destroy,但是application仍然存在,后台线程,数据库、content provider也存在,因此尽可能将数据和业务逻辑放在activity之外。
Activity的destory/create过程
配置变化过程中,Activity经历destroy,重新create的过程,有三个回调函数需要关注。
onSaveInstanceState(Bundle outState):当检测到配置变化时会触发此回调函数,在activity的onStop()之前被调用,在此通过Bundle保存数据,并传递到新创建activity的onCreate(Bundle savedInstanceState)和onRestoreInstanceState(Bundle savedInstanceState)的参数中。对于带有android:id的view,系统在onSaveInstanceState()中或自动存储用户输入的内容,并在重建时恢复。因此,如果我们需要重写,要记住调用super.onSaveInstanceState(); 通过bundle保存数据,例如整数使用putInt()方法,对于组合对象,可以采用putParcelable()
onCreate()和onRestoreInstanceState()都可以通过bundle获取信息。一般会在onCreate()中处理,因为那里进行UI初始化的处理。但是有时我们会extends activity,这是在onRestoreInstanceState()中处理有时会更为简单。相关的执行顺序为onCreate() –>onStart() –>onRestoreInstanceState() –> onResume()。
如果我们通过bundle进行数据保留,要注意,这种情况下,旧的activity是不能进行垃圾回收的,存在内存泄漏的风险,因此我们应当避免将activity上下文相关的Drawables、Views、Adapters等对象放入bundle中。如果实现需要,我们可以将之放在activity之外,或者使用某些id索引(int这类不是保持对象,而是赋值)。
Fragment的destory/create过程
onSaveInstanceState():
Fragment和activity一样,可以通过onSaveInstanceState()进行数据保存,可以通过onInflate()、onCreate()、onCreateView()和onActivityCreate()进行获取。Android只保证在onDestroy()之前调用onSaveInstanceState(),不保证具体的执行顺序,因此有可能在调用onSaveInstanceState()时,相关的view容器已经无效,也就是,不应该在onSaveInstanceState()中处理view的数据。有例如,如果fragment在back stack,由于不可视,没有view(即为null),这并非异常,在代码中需要注意。同样,不应将fragment重创建后已不存在的对象进行保留,bundle携带的数据应尽可能地少,减少内存泄漏的风险。
saveFragmentInstanceState():
如果确实需要进行view的处理,可以通过fragment管理器主导要求触发onSaveInstanceState(),如下:
getFragmentManager().saveFragmentInstanceState(this);
saveFragmentInstanceState()将返回Fragment.SavedState对象,这state对象中包含fragment的状态(含有在onSaveInstanceState中保存的bundle),通过setInitialSavedState()可以在新的fragment恢复。我们利用Dialog中的提示框的例子,对例子进行少许修改,实现在下次弹出提示框时,能保留上次的输入值。
public class PromptDialogFragment extends DialogFragment implements OnClickListener{
… …
private static Fragment.SavedState fgState = null; //可以保存在Application的某个对象,为了示范方便,本例子采用静态函数
public static PromptDialogFragment newInstance(String prompt){
PromptDialogFragment pdf = new PromptDialogFragment();
pdf.setInitialSavedState(fgState); //获取保存的状态
... ...
return pdf;
}
@Override //如果fgState非null,那么就可以从得到Bundle数据。在原例子中,新弹框是新建的dialog fragment,和原对话框无关,也不属于配置改变,因此bundle为null。在新例子中,由于我们保存了上一次对话框的state,并在实例创建时恢复,因此可以获取原对话框的state,包括当中的bundle
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
... ...
if(savedInstanceState != null){
CharSequence text = savedInstanceState.getCharSequence("input");
et.setText(text == null ? "" : text);
}
//将原来dismiss的button改为触发信息保存
Button dismissBtn = (Button)v.findViewById(R.id.button_dismiss);
dismissBtn.setOnClickListener(this);
dismissBtn.setText("保存信息");
......
}
@Override
public void onSaveInstanceState(Bundle outState) {
showInfo("onSaveInstanceState() is called");
outState.putCharSequence("input", et.getText());
super.onSaveInstanceState(outState);
}
@Override
public void onClick(View v) {
//saveFragmentInstanceState()将触发onSaveInstanceState()回调函数,进行信息保存,并将保存内容存放在fgState对象中
switch(v.getId()){
case R.id.button_dismiss: //新例子为“信息保存”触发按钮
fgState = getFragmentManager().saveFragmentInstanceState(this);
break;
... ...
}
}
}
onRetainInstance():
通过onRetainInstatnce(true),当activity被destroy和re-created时,fragment的onDestroy()并不会被调用,说明fragment对象仍然存在于app中,在新activity创建时,fragment对象将attach到新的activity中,这个过程无需调用onCreate(),因为并重新创新fragment。我们在原对话框的例子进行测试,在onCreate()中加入onRetainInstatnce(true),进行横竖屏切换,状态跟踪如下。

相关链接: 我的Android开发相关文章
【转】 Pro Android学习笔记(五六):配置变化的更多相关文章
- 【转】 Pro Android学习笔记(六七):HTTP服务(1):HTTP GET
目录(?)[-] HTTP GET小例子 简单小例子 出现异常NetworkOnMainThreadException 通过StrictMode进行处理 URL带键值对 Andriod应用可利用ser ...
- 【转】 Pro Android学习笔记(六五):安全和权限(2):权限和自定义权限
目录(?)[-] 进程边界 声明和使用权限 AndroidManifestxml的许可设置 自定义权限 运行安全通过两个层面进行保护.进程层面:不同应用运行在不同的进程,每个应用有独自的user ID ...
- 【转】 Pro Android学习笔记(六八):HTTP服务(2):HTTP POST
目录(?)[-] 找一个测试网站 HTTP POST小例子 上次学习了HTTP GET请求,这次学习一下HTTP POST. 找一个测试网站 小例子好写,但要找个测试网站就有些麻烦,一下子无从入手,都 ...
- 【转】 Pro Android学习笔记(六九):HTTP服务(3):HTTP POST MultiPart
目录(?)[-] 建立测试环境 开发环境导入第三方JAR HTTP Post Multipart小例子 HTTP POST不仅可以通过键值对传递参数,还可以携带更为复杂的参数,例如文件.HTTP Po ...
- 【转】 Pro Android学习笔记(六三):Preferences(7):代码控制首选项
[-] 代码实现preference 利用preference保存状态 DialogPreference 代码实现preference View可以不通过xml进行设置,有代码直接进行设置,首选项pr ...
- 【转】 Pro Android学习笔记(六二):Preferences(6):header
目录(?)[-] 代码实现 header xml文件 在前面的例子,我们主要学习了PreferenceScreen的xml如何写,preference有哪些类型.在代码中,我们为了不提示warning ...
- 【转】 Pro Android学习笔记(六十):Preferences(4):MultiSelect List Preference
目录(?)[-] XML文件 在设备中保存 读出信息 ListPreference提供单选列表,我们可以通过CheckBoxPreference提供多选列表.此外,Android在3.0后提供Mult ...
- 【转】 Pro Android学习笔记(六四):安全和权限(1):签发apk
目录(?)[-] Android安全模型 数字证书签发 Debug的keystore 生产unsigned的apk 为apk进行证书签发 align安装包 使用Export Wizard生成签发的ap ...
- 【转】Pro Android学习笔记(六):了解Content Provider(中)
Content Provider的架构 Authority类似web中的域名,每个content provider会通过AndroidManifest.xml向系统注册authority,如下.其中n ...
- Pro Android学习笔记(一三七):Home Screen Widgets(3):配置Activity
文章转载仅仅能用于非商业性质,且不能带有虚拟货币.积分.注冊等附加条件.转载须注明出处http://blog.csdn.net/flowingflying/以及作者@恺风Wei. 通过widget定义 ...
随机推荐
- Bootstrap学习-菜单-按钮-导航
1.下拉菜单(基本用法) 在使用Bootstrap框架的下拉菜单时,必须调用Bootstrap框架提供的bootstrap.js文件.当然,如果你使用的是未编译版本,在js文件夹下你能找到一个名为“d ...
- threading.local的作用?
threading.local()这个方法的特点用来保存一个全局变量,但是这个全局变量只有在当前线程才能访问,如果你在开发多线程应用的时候 需要每个线程保存一个单独的数据供当前线程操作,可以考虑使用 ...
- 自定义弹窗 VS AlertDialog分享弹窗
一.摘要 弹窗通常用于提示用户进行某种操作,比如:点击分享按钮,弹窗分享对话框:双击返回按钮,弹窗退出对话框:下载文件,提示下载对话框等等,分享对话框/退出对话框/下载对话框,都可以直接使用Alert ...
- Django继承HTML模板
Django在渲染模板的过程中可以实现模板样式的继承,以减少重复的代码 1.extend继承 模板.html: 模板内容 {{% block name1 %}} {{% enfblock %}} #n ...
- 了解CentOS服务器的基本信息
简单描述了如何从CPU.内存.硬盘性能.负载方面去了解自己工作的服务器性能.这个很重要,必须了解机器的方方面面才能提高在自己运维工作效率. 一.查看linux服务器cpu详情 查看物理cpu个数: [ ...
- Yii2 高级查询
首先我们要自己写一个ActiveQuery 类并且继承 Yii2 的 ActiveQuery: namespace api\models; class ActiveQuery extends \yii ...
- keep-alive使用笔记
vue2.0提供了keep-alive组件,用来缓存组件,避免多次加载,减少性能消耗. 1.将整个网页缓存起来 <router-view class="view" keep- ...
- hbase shell-security(安全指令)
hbase shell安全指令篇: grant list_security_capabilities revoke user_permission 正在编辑中
- TP里的关联查询
$res = $db->join('b on a.ex_id = b.pe_eid')->select(); 注意:这里的表a.表b需要带表前缀
- J2EE 领域的一些技术框架结构图
J2EE 领域的一些技术框架结构图 阿里百川,开启移动应用开发的新篇章 1.Spring 架构图 Spring 是一个开源 框架,是为了解决企业应用程序开发复杂性而创建的.框架的主要优势之 ...