IllegalStateException异常更换一个片段时,片段、异常、IllegalStateException

2023-09-12 01:28:57 作者:已定成败。

这是一个使用兼容包小了Android 2.2的测试应用程序。这是(错误,当然)方式,我尝试更换一个片段收到点击时。我试图用同样的片段类的新(不同)的实例来替换。正如我将解释它没有预想工作,我需要帮助:

It's small Android 2.2 test application using the Compatibility Package. This is the (wrong, of course) way I try to replace a Fragment when receiving a click. I'm trying to replace it with a new (different) instance of the same Fragment class. As I will explain it doesn't work as expected and I need help:

public class MainFragmentActivity extends FragmentActivity {
  ...

  public void myAction(View view) {
    ...
    RightFragment newRightFrag = RightFragment.newInstance(myNewOption);
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
    ft.replace(R.id.landscape_right_fragment, newRightFrag);
    ft.commit();
  }
}

您一定已经看到了我的错误是。反正让我们给什么应用程序应该做更多的解释:

You will surely have seen what my mistake is. Anyway let's give a little more explaination about what the application should do :

横向:

---------                ----------
| L | R |  -> click ->   | L | R2 |
---------                ----------

在横向,活动具有2片段一个观点: leftLand 的&放大器; 的 rightLand 的,如果你点击该片段的按钮的 leftLand 的,那么它​​的变化会创建一个新的片段,并替代了的 rightLand 的片段的实例具有相同的FragamentActivity类的另一个实例。是什么让不同的两个实例是传递给的newInstance(INT),它是基于点击按钮的参数。

On landscape orientation, the activity has a view with 2 fragments: "leftLand" & "rightLand", and if you click a button of the fragment "leftLand" then it changes creates a new Fragment and substitutes the "rightLand" Fragment instance with another instance of the same FragamentActivity class. What makes different those two instances is a parameter passed to "newInstance(int)", it's based upon the clicked button.

纵向:

-----                  -----
|   |                  |   |
| L |   -> click ->    | R |
|   |                  |   |
-----                  -----

在纵向它只是展示了分段的 leftPort 的(有相同的布局的 leftLand 的),如果你点击了按钮,然后它会启动一个Intent的启动RightFragmentActivity,这说明碎片的 rightLand 的

In portrait orientation it just shows the fragment "leftPort" (has the same layout as "leftLand") and if you click its button then it launches an Intent an starts the RightFragmentActivity, which shows the Fragment "rightLand"

它工作正常,如果我不更换合适的片段。如果我这样做(点击横向按钮),然后在随后的方向变化(该活动的启动)的的FragmentActivity无法启动,因为一个 IllegalStateException异常的:片段RightFragment做不是创建一个视图是这样的:

It works fine ... if I don't replace the right fragment. If I do it (clicking the button in landscape orientation) then on a subsequent orientation change (restart of the activity) the FragmentActivity isn't able to start because of a "IllegalStateException: Fragment RightFragment did not create a view" like this :

D/AndroidRuntime( 1428): Shutting down VM
W/dalvikvm( 1428): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
E/AndroidRuntime( 1428): FATAL EXCEPTION: main
E/AndroidRuntime( 1428): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.agm.test/com.agm.test.MainFragmentActivity}: android.view.InflateException: Binary XML file line #13: Error inflating class fragment
E/AndroidRuntime( 1428):        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
E/AndroidRuntime( 1428):        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
E/AndroidRuntime( 1428):        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3815)
E/AndroidRuntime( 1428):        at android.app.ActivityThread.access$2400(ActivityThread.java:125)
E/AndroidRuntime( 1428):        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2037)
E/AndroidRuntime( 1428):        at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 1428):        at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime( 1428):        at android.app.ActivityThread.main(ActivityThread.java:4627)
E/AndroidRuntime( 1428):        at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 1428):        at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime( 1428):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
E/AndroidRuntime( 1428):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
E/AndroidRuntime( 1428):        at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 1428): Caused by: android.view.InflateException: Binary XML file line #13: Error inflating class fragment
E/AndroidRuntime( 1428):        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:582)
E/AndroidRuntime( 1428):        at android.view.LayoutInflater.rInflate(LayoutInflater.java:618)
E/AndroidRuntime( 1428):        at android.view.LayoutInflater.inflate(LayoutInflater.java:407)
E/AndroidRuntime( 1428):        at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
E/AndroidRuntime( 1428):        at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
E/AndroidRuntime( 1428):        at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:198)
E/AndroidRuntime( 1428):        at android.app.Activity.setContentView(Activity.java:1647)
E/AndroidRuntime( 1428):        at com.agm.test.MainFragmentActivity.onCreate(MainFragmentActivity.java:25)
E/AndroidRuntime( 1428):        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
E/AndroidRuntime( 1428):        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
E/AndroidRuntime( 1428):        ... 12 more
E/AndroidRuntime( 1428): Caused by: java.lang.IllegalStateException: Fragment com.agm.test.RightFragment did not create a view.
E/AndroidRuntime( 1428):        at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:287)
E/AndroidRuntime( 1428):        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:558)
E/AndroidRuntime( 1428):        ... 21 more
W/ActivityManager(   59):   Force finishing activity com.agm.test/.MainFragmentActivity

我已认识到,旧的 RightFragment 的不被破坏之后被替换。这可能是我的错误的方式,试图取代它的结果。

I have realized that the old "RightFragment" is not destroyed after been replaced. This is probably a consequence of my wrong way to try to substitute it.

任何帮助将是非常美联社preciated。

Any help would be really appreciated.

在此先感谢!

/天使·加林多·穆尼奥斯

/ Angel Galindo Muñoz

推荐答案

我想你可能误会了我的意见,所以我会在这里提供了更详细的解释。

I think you may have misunderstood my comment, so I'll offer a more detailed explanation here.

的一个问题是通常产生与移除或替换片段试图移除已添加到布局通过XML而不是编程在Java中的片段。这是不可以一样膨胀片段自身布局的片段的Java code中的 onCreateView()功能(这就是你似乎是描述你的回应我的意见)。为了说明什么,我说什么,我会告诉你两种方式,人们试图删除/替换片段。

One problem that commonly arises with removing or replacing fragments is trying to remove a fragment that has been added to the layout through XML instead of programmatically in Java. This is not the same as inflating the fragment's own layout in the onCreateView() function of the fragment's Java code (this is what you seem to be describing in your response to my comment). To illustrate what I'm talking about, I'll show you two ways that people try to remove/replace fragments.

这是错误的方式做到这一点:

XML布局:的

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">

    <fragment android:name="com.example.ExampleFragment"
    android:id="@+id/example_fragment"
    android:layout_weight="1"
    android:layout_width="0dp"
    android:layout_height="match_parent" />

</LinearLayout>

Java的:的

swapFragment()
{
    Fragment newFragment = new ExampleFragment();
    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    transaction.replace(R.id.fragment_container, newFragment);
    transaction.addToBackStack(null);
    transaction.commit();
}

这code,也不会在你期望的方式执行。这是在XML布局中添加的初始片段不会被删除。这是因为XML布局旨在描述静态布局元素。您可以在运行时改变自己的内容,或者隐藏它们,但你不能从布局删除这些东西。这是戴安娜Hackborn在说的discussion螺纹我挂了。

This code, will not execute in the way that you expect. The initial fragment that is added in the XML layout will not be removed. This is because XML layouts are intended to describe static layout elements. You can change their contents at run time, or hide them, but you can't delete these things from the layout. This is what Dianne Hackborn was saying in the discussion thread I linked to before.

这是正确的方式做到这一点(至少在我的经验):

XML布局:的

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">

    <!-- Fragment will go here eventually, but it's not added in the layout -->

</LinearLayout>

Java的:的

protected void onCreate(Bundle savedInstanceState)
{
     super.onCreate(savedInstanceState);
     setContentView(R.layout.my_layout);

     ExampleFragment newFragment = new ExampleFragment();
     FragmentTransaction transaction = getFragmentManager().beginTransaction();
     transaction.add(R.id.fragment_container, newFragment);
     transaction.commit();
}

...

swapFragment()
{
    Fragment newFragment = new ExampleFragment();
    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    transaction.replace(R.id.fragment_container, newFragment);
    transaction.addToBackStack(null);
    transaction.commit();
}

此策略不会在初始布局中添加片段。相反,它增加了它在Java code创建活动的时候。这使得它从布局移除(或者使用删除()更换()

This strategy does not add the fragment in the initial layout. Instead it adds it in the Java code when the Activity is created. This allows it to be removed from the layout (either using remove() or replace())

这可能不是解决你的问题,但它是碎片创建一个共同的难题。你可以确保你所添加的片段在适当的方式,让他们被删除,然后如果不解决这个问题,我们可以进一步解决。

This might not solve your problem, but it is a common difficulty that Fragments create. You can make sure that you are adding the Fragments in the proper way to allow them to be removed, and then if that doesn't solve the problem we can troubleshoot further.

 
精彩推荐