Fragment事务提交的方式
2016-01-26 19:02
309 查看
一.概述
在Android中,我们一般会使用FragmentTransaction的commit方法来提交事务,但是在有些情况下,调用这个方法去提交事务是会发生异常的,先让大家看一下会发生什么异常:意思就是告诉你不能在onSaveInstanceState方法之后去提交事务,这种异常的出现是由于,在Activity的状态保存之后,尝试去提交一个FragmentTransaction,这种现象被称为活动状态丢失。下面贴上发生异常的代码。
[code]public class MainActivity extends FragmentActivity { private FragmentManager manager; private FragmentTransaction transaction; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); manager = getSupportFragmentManager(); transaction = manager.beginTransaction(); transaction.replace(R.id.fl_main,new FragmentOne()); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); transaction.commit(); } }
二.发生异常的原因
在activity可能被系统销毁之前,系统会调用onSaveInstanceState方法,给这个方法传递了一个Bundle对象。Activity可以通过这个对象来存储它的状态,而且Activity把它的dialogs、fragments以及views的状态都保存在这个对象里面。当这个函数返回时,系统打包这个Bundle对象通过一个Binder接口传递给系统服务处理,然后它会被安全的存储下来。当系统决定重新创建这个Activity的时候,它会给这个应用传回一个相同的Bundle对象,通过这个对象可以重新装载Activity销毁时的状态。那为什么会抛出这个异常呢?这个问题源于这样的事实,Bundle对象代表一个Activity在调用onSaveInstanceState()方法的一个瞬间快照,仅此而已。这意味着,当你在onSaveInstanceState()方法调用后会调用FragmentTransaction的commit方法。这个transaction将不会被记住,因为它没有在第一时间记录为这个Activity的状态的一部分。从用户的角度来看,这个transaction将会丢失,可能导致UI状态丢失。为了保证用户的体验,Android不惜一切代价避免状态的丢失。因此,无论什么时候发生,都将简单的抛出一个IllegalStateException异常。三.如何避免这个异常
1.当你在Activity生命周期函数里面提交transactions的时候要小心。大部分的应用仅仅在onCreate()方法被调用的开始时间提交transactions,或者在响应用户输入的时候,因此将不可能碰到任何问题。然而,当你的transactions在其他的Activity生命周期函数提交,如onActivityResult()、onStart()和onResume(),事情将会变得微妙。例如,你不应该在FragmentActivity的onResume()方法中提交transactions。因为有些时候这个函数可以在Activity的状态恢复前被调用。如果你的应用要求在除onCreate()函数之外的其他Activity生命周期函数中提交transaction,你可以在FragmentActivity的onResumeFragments()函数或者Activity的onPostResume()函数中提交。这两个函数确保在Activity恢复到原始状态之后才会被调用,从而避免了状态丢失的可能性。2。避免在异步回调函数中提交transactions。包括常用的方法,比如AsyncTask的onPostExecute方法和LoaderManager.LoaderCallbacks的onLoadFinished方法。在这些方法中执行transactions的问题是,当他们被调用的时候,他们完全没有Activity生命周期的当前状态。例如,考虑下面的事件序列:
一个Activity执行一个AsyncTask。
用户按下“Home”键,导致Activity的onSaveInstanceState()和onStop()方法被调用。
AsyncTask完成并且onPostExecute方法被调用,而它没有意识到Activity已经结束了。
在onPostExecute函数中提交的FragmentTransaction,导致抛出一个异常。
一般来说,避免这种类型异常的最好办法就是不要在异步回调函数中提交transactions。如果你的应用需要在这些回调函数中执行transaction,而没有简单的方法可以确保这个回调函数是否在onSaveInstanceState()之后调用。你可能需要使用commitAllowingStateLoss方法,并且处理可能发生的状态丢失。
3.作为最后的办法,使用commitAllowingStateLoss()函数。commit()函数和commitAllowingStateLoss()函数的唯一区别就是当发生状态丢失的时候,后者不会抛出一个异常。通常你不应该使用这个函数,因为它意味可能发生状态丢失。当然,更好的解决方案是commit函数确保在Activity的状态保存之前调用,这样会有一个好的用户体验。除非状态丢失的可能无可避免,否则就不应该使用commitAllowingStateLoss()函数。
如何在onActivityResult中提交事物:
[code]public class MainActivity extends FragmentActivity { private FragmentManager manager; private FragmentTransaction transaction; boolean flag = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); manager = getSupportFragmentManager(); transaction = manager.beginTransaction(); transaction.replace(R.id.fl_main,new FragmentOne()); } public void start(View view){ Intent intent = new Intent(this,SecondActivity.class); startActivityForResult(intent,0); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { Toast.makeText(this,"onactivity",Toast.LENGTH_LONG).show(); // transaction.commit(); flag = true; super.onActivityResult(requestCode, resultCode, data); } @Override protected void onPostResume() { if(flag) transaction.commit(); super.onPostResume(); } }
相关文章推荐
- JavaSE入门学习10:Java修饰符
- Linux多线程服务端编程:使用muduo C++网络库
- SDIO驱动的命令从何玩起?
- MR-2.输入格式(InputFormat)基本介绍
- 操作注册表的API函数介绍(RegCreateKeyEx:该函数用来创建注册表键,如果该键已经存在,则打开它)
- android多线程断点续传下载
- Codeforces Round #326 (Div. 2) E. Duff in the Army(LCA+倍增法)
- 关于SQL语句的使用心得
- linux下查看路由表、默认路由器
- 数据结构---无重复元素链表的实现
- JavaScript基础
- linux命令(2):df 磁盘占用
- Android的底层库libutils介绍
- 使用lua代码创建文件夹,解压zip文件到指定目录(亲测可用)
- 大话重构连载6:一个真实的谎言
- 学习Slim Framework for PHP v3 (三)
- web项目中文乱码问题实践经验(springmvc +hibernate)
- Spy++的使用方法
- Postgresql通过批处理命令执行sql文件
- 23岁产妇坐月子双腿险被截肢,产后绝对不能做这八件事!