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

标签 android 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中的两个widget相互引用引起的,但这里肯定不是这样。 我在此布局文件(底部)中使用了 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);
}

有没有人遇到过这样的事情?非常感谢任何帮助...

最佳答案

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

关于android - RelativeLayout 中的循环依赖引起的奇怪的 IllegalStateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13524751/

相关文章:

android - 应用程序android中的库依赖类使用

android - 错误 :Execution failed for task ':app:packageRelease' . > java.io.IOException:无法读取 zip 文件

java - 与 RelativeLayout 底部对齐的按钮被截断

android - 如何将一个 TextView 与另一个断到下一行的 TextView 右侧对齐?

android - startForegroundService() 在 Oreo 中抛出 IllegalStateException on app BOOT_COMPLETED

android - 运行时位置权限 - GoogleApiClient 尚未连接

android - 在android中膨胀层形状列表

android - subview 的坐标何时生效?

java - 命中 java.lang.IllegalStateException : null when call setAttribute() in HttpSession

java - 什么是 IllegalStateException?