Fragment事务提交的方式

一.概述

在Android中,我们一般会使用FragmentTransaction的commit方法来提交事务,但是在有些情况下,调用这个方法去提交事务是会发生异常的,先让大家看一下会发生什么异常:

这里写图片描述

意思就是告诉你不能在onSaveInstanceState方法之后去提交事务,这种异常的出现是由于,在Activity的状态保存之后,尝试去提交一个FragmentTransaction,这种现象被称为活动状态丢失。下面贴上发生异常的代码。

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中提交事物:

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();
    }
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Android,可以使用FragmentManager来管理Fragment的跳转。具体步骤如下: 1. 获取FragmentManager对象: FragmentManager fragmentManager = getSupportFragmentManager(); 2. 开始Fragment事务FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 3. 创建要跳转的Fragment对象: MyFragment myFragment = new MyFragment(); 4. 调用FragmentTransaction的replace方法,将当前Fragment替换为要跳转的FragmentfragmentTransaction.replace(R.id.container, myFragment); 5. 调用FragmentTransaction的commit方法提交事务fragmentTransaction.commit(); 其,R.id.container是一个FrameLayout,用于显示Fragment的布局容器。 ### 回答2: 在Android使用Fragment的一个常见的需求是在一个Fragment点击某个按钮或者view后跳转到另一个Fragment,也就是所谓的Fragment跳转Fragment。 在实现这个需求之前,需要先明确一些基本概念。在Android使用Fragment的最基本的方式使用FragmentTransaction来进行添加、移除、替换、隐藏等操作。当一个新的Fragment需要被展示时,也就是所谓的Fragment跳转Fragment时,我们需要使用FragmentTransaction来进行以下步骤: 1. 创建要跳转的Fragment实例。 2. 使用FragmentManager获取FragmentTransaction实例。 3. 调用FragmentTransaction的替换方法(replace)来将当前Fragment替换为要跳转的Fragment。 4. 添加到回退栈(addToBackStack)。 5. 调用FragmentTransaction的提交方法(commit)来提交这一操作。 示例代码如下: ``` FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.fragment_container, new MyFragment()); transaction.addToBackStack(null); transaction.commit(); ``` 在这段代码,我们使用了SupportFragmentManager来获取了一个FragmentTransaction对象,并将其替换为了新的Fragment,并将其添加到回退栈。最后,调用了提交方法提交这一操作。 需要注意的是,在跳转Fragment时,我们也可以传递一些数据给新的Fragment,例如某些参数、对象等。我们可以使用Bundle将这些数据打包传递给新的Fragment。在新的Fragment,我们可以使用getArguments()方法获取这些数据。 总体来说,Fragment跳转Fragment是Android常见的一种场景,使用FragmentTransaction进行操作可以轻松地实现这一需求。在进行操作时,需要注意保存当前状态并添加到回退栈,以便用户可以使用返回按钮返回上一个Fragment。 ### 回答3: Fragment 跳转 Fragment 是指在一个 Fragment 通过代码的方式启动另一个 Fragment。在实际开发,这种方式常常被用于实现页面之间的跳转或者数据的传递等操作。 在 Android Fragment 跳转 Fragment 有多种方式,其最常用的方式使用 FragmentManager 开启一个新的 Fragment,具体流程如下: 1. 首先需要获取到 FragmentManager 对象,可以通过 getActivity().getSupportFragmentManager() 方法获取当前 Fragment 所在的 Activity 的 FragmentManager 对象。 2. 创建一个新的 Fragment 对象,这个对象可以在 FragmentManager 进行管理,在后面我们会用到。 3. 随着 Fragment 的增多,一个问题也就显现出来,如何在父 Fragment 实现多个 Fragment 之间的切换?这个时候可以选择使用 FragmentTransaction 对象,通过 add()、replace() 等方法实现对 Fragment 的增删操作。 代码实现如下: // 获取 FragmentManager 对象 FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); // 创建一个新的 Fragment 对象 SecondFragment fragment = new SecondFragment(); // 开启一个事务 FragmentTransaction transaction = fragmentManager.beginTransaction(); // 通过 add()、replace() 等方法实现对 Fragment 的增删操作 transaction.replace(R.id.container, fragment); transaction.addToBackStack(null); // 提交事务,启动 Fragment transaction.commit(); 在这段代码,R.id.container 表示存放 Fragment 的容器,这个可以根据实际需要进行修改。 同时,我们还需要注意 addToBackStack() 方法使用。这个方法可以将当前 Fragment 加入 BackStack ,也就是将当前 Fragment 放入到一个栈,方便用户在返回时直接返回到上一个 Fragment。需要注意的是,如果不使用 addToBackStack() 方法,则用户在返回时会直接退出当前 Activity。 总之,Fragment 跳转 Fragment 功能十分重要,能够帮助开发者实现程序各种场景的操作。通过 Fragment 嵌套来实现页面嵌套,通过 Fragment 之间的跳转来实现页面之间的切换,是 Android 开发不可或缺的一部分。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值