由RelativeLayout中的循环依赖引起的奇怪的IllegalStateException

时间:2012-11-23 07:31:50

标签: android relativelayout illegalstateexception

我的Android项目出现了一个奇怪的错误。有时,应用程序崩溃时会出现此IllegalStateException:

11-23 08:20:51.610: E/AndroidRuntime(16714): FATAL EXCEPTION: main
11-23 08:20:51.610: E/AndroidRuntime(16714): java.lang.IllegalStateException: Circular dependencies cannot exist in RelativeLayout
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.widget.RelativeLayout$DependencyGraph.getSortedViews(RelativeLayout.java:1286)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.widget.RelativeLayout.sortChildren(RelativeLayout.java:294)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:314)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.view.View.measure(View.java:12775)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4709)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1385)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.widget.LinearLayout.measureVertical(LinearLayout.java:670)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.widget.LinearLayout.onMeasure(LinearLayout.java:563)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.view.View.measure(View.java:12775)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4709)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.widget.FrameLayout.onMeasure(FrameLayout.java:293)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.view.View.measure(View.java:12775)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.widget.LinearLayout.measureVertical(LinearLayout.java:822)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.widget.LinearLayout.onMeasure(LinearLayout.java:563)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.view.View.measure(View.java:12775)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4709)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.widget.FrameLayout.onMeasure(FrameLayout.java:293)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2240)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.view.View.measure(View.java:12775)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1117)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2505)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.os.Handler.dispatchMessage(Handler.java:99)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.os.Looper.loop(Looper.java:137)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at android.app.ActivityThread.main(ActivityThread.java:4514)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at java.lang.reflect.Method.invokeNative(Native Method)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at java.lang.reflect.Method.invoke(Method.java:511)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
11-23 08:20:51.610: E/AndroidRuntime(16714):    at dalvik.system.NativeStart.main(Native Method)

我知道这应该是由RelativeLayout中相互引用的两个小部件引起的,但在这里肯定不是这样。 我在这个布局文件中使用了RelativeLayout(在底部):

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

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="450dp" >

    <fragment
        android:id="@+id/identification_navigation_fragment"
        android:name="plt.demonstrator.common.NavigationFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <View
        android:id="@+id/view1"
        android:layout_width="3dp"
        android:layout_height="match_parent"
        android:layout_weight="0"
        android:background="@color/lightgray" />

    <fragment
        android:id="@+id/identification_fragment"
        android:name="plt.demonstrator.identifikation.IdentificationFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3.5" />

</LinearLayout>

<RelativeLayout
    android:id="@+id/bottom_actionbar"
    android:layout_width="match_parent"
    android:layout_height="48dp"
    android:layout_gravity="center_vertical"
    android:background="#DDDDDD" >

</RelativeLayout>

项目在运行时动态添加,无论是左侧还是右侧。所以实际上左边的物品没有引用右侧的东西,反之亦然。 此外,我无法识别导致此异常的代码的任何部分,调试器将运行直到onResume()完成且应用程序处于恢复状态。这是添加项目的代码,但正如我所说,调试器并没有与此争论......

public static void addActionbarItem(RelativeLayout actionbar, Context ctx, int itemid, int textid, 
        int iconid, Direction direction, View.OnClickListener listener) {
    TextView item = new TextView(ctx);
    item.setText(ctx.getString(textid).toUpperCase());
    item.setTextAppearance(ctx, android.R.style.TextAppearance_Medium);
    int paddingPx = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12, ctx.getResources().getDisplayMetrics());
    item.setPadding(paddingPx, 0, paddingPx, 0);
    item.setGravity(Gravity.CENTER_VERTICAL);
    item.setId(itemid);

    Drawable icon = ctx.getResources().getDrawable(iconid);
    icon.setBounds(0, 0, 24, 24);
    item.setCompoundDrawables(icon, null, null, null);

    RelativeLayout.LayoutParams separatorParams = new LayoutParams(1, 32);

    // vertical separator
    View separator = new View(ctx);
    int color = ctx.getResources().getColor(android.R.color.secondary_text_light);
    separator.setBackgroundColor(color);
    separator.setId(separatorId++);
    separatorParams.setMargins(0, 8, 0, 0);

    RelativeLayout.LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);

    if (direction == Direction.LEFT) {
        // Item should be added at left side
        if (leftAnchor != -1) {
            // There is already an item at left side -> place the new item right to it
            separatorParams.addRule(RelativeLayout.RIGHT_OF, leftAnchor);
            separator.setLayoutParams(separatorParams);
            actionbar.addView(separator);
            params.addRule(RelativeLayout.RIGHT_OF, separator.getId());
        } else {
            // Item is the first on left side, place it at left edge
            params.addRule(RelativeLayout.ALIGN_PARENT_LEFT, -1);
            // Add some space to the display edge
            params.setMargins(8, 0, 0, 0);
        }
        // Update anchor ID
        leftAnchor = itemid;
    } else {
        // Item should be added at right side
        if (rightAnchor != -1) {
            // There is already an item at right side -> place the new item left to it
            separatorParams.addRule(RelativeLayout.LEFT_OF, rightAnchor);
            separator.setLayoutParams(separatorParams);
            actionbar.addView(separator);
            params.addRule(RelativeLayout.LEFT_OF, rightAnchor);
        } else {
            // Item is the first on right side, place it at right edge
            params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, -1);
            // Add some space to the display edge
            params.setMargins(0, 0, 8, 0);
        }
        // Update anchor ID
        rightAnchor = itemid;
    }

    item.setLayoutParams(params);
    // Set item behaviour
    item.setOnClickListener(listener);
    // Add a touch listener for visual feedback
    // Touch listener is invoked before click listener, so event must be forwarded after onTouch method
    item.setOnTouchListener(new View.OnTouchListener() {

        public boolean onTouch(final View v, MotionEvent e) {
            // ICS clicked button style
            v.setBackgroundColor(0x880099CC);
            v.invalidate();
            Runnable timer = new Runnable() {
                public void run() {
                    // Reset color
                    v.setBackgroundColor(Color.TRANSPARENT);
                    v.invalidate();
                }
            };
            Handler h = new Handler();
            h.removeCallbacks(timer);
            // Reset button style after 50ms
            h.postDelayed(timer, 50);
            // Forward event to OnClickListener
            return false;
        }
    });

    actionbar.addView(item);
}

有人已经面对这样的事吗?非常感谢任何帮助...

1 个答案:

答案 0 :(得分:2)

在logcat中打印出你的id,对于你动态添加的所有视图,你一定会找到一个在你的布局中定义循环依赖的视图。您的代码不容易理解,但您的错误就在那里。