Java Android 调试器隐藏局部变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20271171/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 00:45:00  来源:igfitidea点击:

Android debugger hides local variable

javaandroiddebuggingundefined-behavior

提问by spacebiker

I have a weird behavior using Android's debugger when executing the following code. The variable valuedisappears just after it has been initialized by the widget. I moved it to to watches but it says "Cannot find local variable value". It does not matter where I place the variable, before the for loop or inside, it behaves the same no matter what. I also printed the variable as you can see in the code and it says "value is null"but when I check it by if (value == null)it does not stop and finally throws an error when trying to cast it to an integer.

在执行以下代码时,我使用 Android 的调试器有一个奇怪的行为。变量在小部件初始化后立即消失。我把它移到手表上,但它说"Cannot find local variable value"。无论我把变量放在哪里,在 for 循环之前还是内部,它的行为都是一样的。我还打印了变量,正如您在代码中看到的那样,它说"value is null"但是当我检查它时,if (value == null)它不会停止并最终在尝试将其转换为整数时抛出错误。

The code:

编码:

    for (int i=0; i < (view != null ? ((ViewGroup)view).getChildCount() : 0); i++)
    {
        // Get name of the widget for example field__id,
        // Convert to field name replacing field__id for id
        // or for example field_name to name
        // Check if the field exists in the column name, if so, add the ContentValue
        View widget = ((ViewGroup)view).getChildAt(i);
        String widgetName = view.getResources().getResourceEntryName(widget.getId());
        String fieldName = widgetName.replace(Model.fieldPrefix,"");
        Object value = null;

        if (columnNames.contains(fieldName)) {
            // TableField on the table matches the field on the form
            try {
                if (widget instanceof TextView) {
                    value = ((TextView) widget).getText().toString();
                } else if (widget instanceof Spinner) {
                    value = ((SpinnerRow) ((Spinner) widget).getSelectedItem()).getId();
                } else if (widget instanceof DatePicker) {
                    String date = AppDatabase.formatDateTime( getContext(), ((DatePicker) widget).getYear() + "-" + ((DatePicker) widget).getMonth() + "-" + ((DatePicker) widget).getDayOfMonth());
                    contentValues.put(fieldName, date ) ;
                } else {
                    throw new ClassCastException("Could not cast the widget"+widget.getClass().toString());
                }
                Log.d(AppController.DEBUG_TAG, "Widget "+widgetName+" value is " + value.toString());

            } catch (NullPointerException e) {
                // Ignore exception:
                value = null;
            }

            TableField tableField = this.getTable().getFieldByName(fieldName);

            if ( (tableField.isPrimaryKey() && (value.equals("-1") || value.equals("")))
                    || !tableField.getNotNull() && value.toString().length()==0  )
                value = null;

            if ( value == null || tableField.getType() == SQLiteCursor.FIELD_TYPE_NULL ) {
                contentValues.putNull(fieldName);
            } else  if (tableField.getType() == SQLiteCursor.FIELD_TYPE_STRING || tableField.getType() == SQLiteCursor.FIELD_TYPE_VARCHAR) {
                contentValues.put(fieldName, String.valueOf(value));
            } else if (tableField.getType() == SQLiteCursor.FIELD_TYPE_INTEGER) {
                contentValues.put(fieldName, Integer.valueOf(value.toString()) );
            } else if (tableField.getType() == SQLiteCursor.FIELD_TYPE_FLOAT) {
                contentValues.put(fieldName,Float.valueOf(value.toString()));
            } else if (tableField.getType() == SQLiteCursor.FIELD_TYPE_BLOB) {
                contentValues.put(fieldName,String.valueOf(value));
            }

        }

    }

回答by Sasa Sekulic

Do you use proguard with obfuscation?

您是否使用混淆器进行混淆?

If yes, that might be the problem - disable it with

如果是,那可能是问题所在 - 禁用它

-dontobfuscate

which you should put in your file with proguard rules (usually proguard-rules.txt, check your proguard config in the build.gradle file, like in the example below:

你应该把它和 proguard 规则放在你的文件中(通常是 proguard-rules.txt,在 build.gradle 文件中检查你的 proguard 配置,如下例所示:

buildTypes {
        debug {
            runProguard true
            zipAlign true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            signingConfig signingConfigs.debug
            testCoverageEnabled true
        }
}

回答by hasan

A similar problem caused by a bug in the gradle version 1.0.0which has beed solved in a later version 1.0.1

由 gradle 中的 bug 引起的类似问题version 1.0.0已在稍后解决version 1.0.1

Search your project for 'com.android.tools.build:gradle:1.0.0'which will be found in build.gradlefiles. you may have more than one build.gradlefile if you are including modules.

搜索'com.android.tools.build:gradle:1.0.0'将在build.gradle文件中找到的项目。build.gradle如果您包含模块,您可能有多个文件。

whenever you have:

每当您有:

'com.android.tools.build:gradle:1.0.0'

'com.android.tools.build:gradle:1.0.0'

Change it to:

将其更改为:

'com.android.tools.build:gradle:1.0.1'

'com.android.tools.build:gradle:1.0.1'

Then sync gradle. Android Studio will download the new gradle jar file and compiles with it.

然后同步gradle。Android Studio 将下载新的 gradle jar 文件并使用它进行编译。

回答by princecharmx

This is what worked for me. Android studio cannot show local variable data when used with Proguard.

这对我有用。与 Proguard 一起使用时,Android Studio 无法显示局部变量数据。

Following settings need to be used during debugging:

调试时需要用到以下设置:

1.

1.

Either add -donotobfuscate property under proguard-rules.pro file, -dontobfuscate OR

在 proguard-rules.pro 文件下添加 -donotobfuscate 属性,-dontobfuscate 或

2.

2.

Under debug buildtypes inside build.grade, minifyEnabled false shrinkResources false

在 build.grade 中的 debug buildtypes 下,minifyEnabled false shrinkResources false

Latter option is more recommended as ur production apk many need to be compressed.

更推荐使用后一个选项,因为您的生产 apk 很多都需要压缩。

buildTypes {
    debug {
        applicationIdSuffix '.debug'
        versionNameSuffix '-DEBUG'
        minifyEnabled false
        shrinkResources false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
    release {
        minifyEnabled true
        shrinkResources true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.release
    }
}

回答by Miklós Keresztes

If your build uses the Hyman toolchainthis can be the source of the problem. In my case, disabling Hyman solves the problem:

如果您的构建使用Hyman 工具链,这可能是问题的根源。就我而言,禁用 Hyman 可以解决问题:

buildTypes {
...
    debug {
        HymanOptions {
            enabled false
        }
    }
}

Note: 1.8 source compatibility requires Hyman!

注意:1.8 源兼容性需要插孔!

回答by Jerry Xiong

I had the same problem. Finally, resolved by removing 'testCoverageEnabled true' from gradle build file.

我有同样的问题。最后,通过从 gradle 构建文件中删除 'testCoverageEnabled true' 来解决。

回答by Jing Li

Having the same problem here: Cannot find local variable '[variable_name]', and the only difference is that my app is fully debuggable, while the issue occurs with the library code.

这里有同样的问题:Cannot find local variable '[variable_name]',唯一的区别是我的应用程序是完全可调试的,而问题发生在库代码上。

I have minifyEnabled falsefor debug buildTypesin both libraryand appmodules. And during debugging, the Build Variantare debugfor both modules as well. Even the generated BuildConfig.javahas the correct value:

minifyEnabled falsedebug buildTypes在这两个应用程序模块。和调试过程中,Build Variantdebug两个模块为好。即使生成BuildConfig.java的值也正确:

public static final boolean DEBUG = Boolean.parseBoolean("true");

public static final boolean DEBUG = Boolean.parseBoolean("true");

Cause:

原因

Gradle doesn't propagate build type (debug or release) of application to its dependent library. It always uses releasebuild of library no matter which build type is chosen in application (the library dependency is specified as compile project(':library')in the app's build.gradle).

Gradle 不会将应用程序的构建类型(调试或发布)传播到其依赖库。release无论在应用程序中选择哪种构建类型,它始终使用库的构建(库依赖项compile project(':library')在应用程序的 build.gradle 中指定)。

Solution:

解决方案

build.gradlein librarymodule

build.gradle模块中

android {
    defaultConfig {
        defaultPublishConfig 'release'
        publishNonDefault true
    }
}

build.gradlein appmodule

build.gradle应用模块中

dependencies {
    debugCompile project(path: ':library', configuration: "debug")
    releaseCompile project(path: ':library', configuration: "release")
}

instead of doing:

而不是做:

compile project(':library')

issue screenshot

问题截图

回答by IC ice

uh... In my case,I just rebuild project to fix it!

呃...在我的情况下,我只是重建项目来修复它!

回答by Miko?aj Biel

Had a similar problem. It was version mismatch between Kotlin used in Android Studio and the one declared in app-level build.gradlefile (probably after Android Studio update). Bumping the version in build.gradlehelped.

有类似的问题。这是 Android Studio 中使用的 Kotlin 与应用级build.gradle文件中声明的 Kotlin 之间的版本不匹配(可能在 Android Studio 更新之后)。碰撞版本有build.gradle帮助。