如何让Fragment自行删除,即它相当于finish()?

PJL*_*PJL 226 android

我正在使用兼容性库转换应用程序以使用片段.现在我有许多活动(ABCD)相互链接,D有一个按钮'OK',当按下调用完成然后冒泡onActivityResult()到另外销毁C和B.

对于我的前Honycomb片段版本,每个活动实际上是片段Af Bf Cf Df的包装器.所有活动都是通过每个片段发起的,startActivityForResult()并且onActivityResult()可以愉快地调用getActivity().finish()

我遇到的问题是在我的Honeycomb版本中我只有一个活动,A,并且片段Bf,Cf,Df使用FragmentManager.

我不明白的是,当按下"确定"以删除片段Df,Cf和Bf时,在Df中该怎么办?

我尝试让片段从堆栈中弹出,但这会导致异常.onActivityResult()是没用的,因为我没有使用加载片段startActivityForResult().

我是否完全以错误的方式思考这个问题?我是否应该实现某种与父片段或活动进行通信的侦听器,以便使用事务管理器进行弹出?

Man*_*ser 312

虽然它可能不是最好的方法,但我能想到的最接近的等价物是支持/兼容性库

getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
Run Code Online (Sandbox Code Playgroud)

要么

getActivity().getFragmentManager().beginTransaction().remove(this).commit();
Run Code Online (Sandbox Code Playgroud)

除此以外.

此外,您可以使用backstack并弹出它.但是请记住,片段可能不在backstack上(取决于在那里获得它的片段事务..)或者它可能不是最后一个进入堆栈,因此弹出堆栈可能会删除错误的...

  • 从PopmentManager中"弹出"片段. (34认同)
  • 虽然这种方法有效,但如果使用addToBackStack(null),它将使后退按钮处理程序+1.所以你必须按两次. (10认同)
  • 这个答案是一种不好的做法,不应该起来投票.片段并不意味着像这样自我意识.它杀死了可重用性,这是碎片的重点!片段应通过任意数量的方式发出活动信号以将其移除.回调接口方法是一种流行的选择.http://developer.android.com/training/basics/fragments/communicating.html (6认同)
  • 我已经尝试了上述过程,但它给出了这个错误“java-lang-illegalstateexception-can-not-perform-this-action-after-onsaveinstance”。所以我必须在哪里删除片段 (2认同)
  • @ManfredMoser我不同意.这是问题的重点.他有一整套碎片要移除.此代码没有空检查或检查是否附加了活动.它会破坏生产,因为它取决于碎片不知道的太多东西. (2认同)

Eri*_*uan 260

你可以使用下面的方法,它工作正常:

getActivity().getSupportFragmentManager().popBackStack();
Run Code Online (Sandbox Code Playgroud)

  • 它在设计方面也比公认的差10倍.片段应该是活动的一个小"帮助者",并且永远不应该控制自身或其他片段 (47认同)
  • 这个答案比接受的答案要好10倍 - 直截了当. (43认同)
  • @avalancha指出,解决方案不正确.请查看http://developer.android.com/guide/components/fragments.html#EventCallbacks (6认同)
  • 我在onActivityResult上使用此方法并获取错误"无法在onSaveInstanceState之后执行此操作".我该如何解决? (2认同)

Com*_*are 58

我不明白的是,当按下"确定"以删除片段Df,Cf和Bf时,在Df中该怎么办?

步骤#1:让Df告诉D"哟!我们得到了OK点击!" 通过调用方法,可以是活动本身,也可以是活动提供的接口实例.

步骤#2:让D移除碎片FragmentManager.

托管活动(D)是知道活动中的其他片段(与其他活动相比)的活动.因此,可能会影响片段混合的片段内事件应传播到活动,这将使适当的编排移动.


Blu*_*ell 35

你应该让Activity处理添加和删除片段,正如CommonsWare所说,使用一个监听器.这是一个例子:

public class MyActivity extends FragmentActivity implements SuicidalFragmentListener {

    // onCreate etc

    @Override
    public void onFragmentSuicide(String tag) {
        // Check tag if you do this with more than one fragmen, then:
        getSupportFragmentManager().popBackStack();
    }
}

public interface SuicidalFragmentListener {
    void onFragmentSuicide(String tag);
}

public class MyFragment extends Fragment {

    // onCreateView etc

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
           suicideListener = (SuicidalFragmentListener) activity;
        } catch (ClassCastException e) {
           throw new RuntimeException(getActivity().getClass().getSimpleName() + " must implement the suicide listener to use this fragment", e);
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // Attach the close listener to whatever action on the fragment you want
        addSuicideTouchListener();
    }

    private void addSuicideTouchListener() {
        getView().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
              suicideListener.onFragmentSuicide(getTag());
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 它没有关闭它*DYING FOREVER*;-( (21认同)
  • 选择接口名称的投票 (8认同)
  • 从技术上讲,如果我们应该让活动杀死片段,那么片段就不会有自杀倾向.这项活动是杀人的. (7认同)
  • 自杀很多emo风格?"SelfClosing"或"AutoClose"或"SmartClose"(r)怎么样 (5认同)
  • 这是一个比其他答案更清晰的方法.活动创建并呈现片段,并应控制其生命周期.当某些事情发生,表明该片段不再应该在视图中时,它应该告诉Activity,并让活动将其删除. (2认同)

Cod*_*sed 17

在Activity/AppCompatActivity中:

@Override
public void onBackPressed() {
    if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
        // if you want to handle DrawerLayout
        mDrawerLayout.closeDrawer(GravityCompat.START);
    } else {
        if (getFragmentManager().getBackStackEntryCount() == 0) {
            super.onBackPressed();
        } else {
            getFragmentManager().popBackStack();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后调用片段:

getActivity().onBackPressed();
Run Code Online (Sandbox Code Playgroud)

或者在其他答案中说明,请在片段中调用:

getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
Run Code Online (Sandbox Code Playgroud)


Gas*_*lén 6

如果您使用的是新的导航组件,则很简单

findNavController().popBackStack()
Run Code Online (Sandbox Code Playgroud)

它会为你完成所有的 FragmentTransaction。