Android“if”块中的怪异行为。

时间:2022-06-04 17:26:59

It walks like a bug, it chirps like a bug.... I need someone to confirm that it's a bug.

走像一个bug,它像虫子一样的啾啾....我需要有人确认这是一个bug。

I was trying to get phone numbers from the address book with this code:

我试着从地址簿中获取这个代码的电话号码:

public JSONObject getAllPhones() throws JSONException{ 
String mPhoneNumberProjection[] = new String[] {
        Contacts.Phones.NAME, Contacts.Phones.NUMBER, Contacts.Phones.TYPE
};
Uri phoneNumbersUri = Contacts.Phones.CONTENT_URI;
JSONObject result = new JSONObject(); 
JSONArray phones = new JSONArray();

Cursor myCursor = mApp.managedQuery(phoneNumbersUri, mPhoneNumberProjection, null, null, null);
mApp.startManagingCursor(myCursor);
if (!myCursor.isAfterLast()){
    myCursor.moveToFirst();
    do{
        JSONObject aRow = new JSONObject();
        for (int i = 0; i < myCursor.getColumnCount(); i++){
            Log.d(LOG_TAG, myCursor.getColumnName(i) + " -> " + myCursor.getString(i));
            aRow.put(myCursor.getColumnName(i), myCursor.getString(i));
        }
        phones.put(aRow);
    } while (myCursor.moveToNext());
}
result.put("phones", phones);
result.put("phoneTypes", getPhoneTypes());
return result;
}

But when there are no contacts, and !myCursor.isAfterLast() evaluates as "false", program steps into "for" loop. So it enters "if" block, skips several methods and lands in "for" loop...

但是,如果没有联系人,并且! mycursors . isafterlast()计算为“false”,那么程序将进入“for”循环。所以它输入if块,跳过几个方法,进入for循环…

When I extract this loop into a separate function, everything works ok.

当我将这个循环提取到一个单独的函数中时,一切正常。

I'm doing this in Eclipse Helios on 32-bit Vista. I tried cleaning the project, erasing Java cache, restarting computer, creating new AVD... I used Android 1.6 and Android 2.2, but the error stays on...

我在32位Vista的Eclipse Helios中做这个。我试着清理项目,删除Java缓存,重新启动计算机,创建新的AVD…我使用了Android 1.6和Android 2.2,但是错误仍然存在……

Can someone explain what's going on?

有人能解释一下发生了什么事吗?

5 个解决方案

#1


1  

It seems that this behavior cannot be reproduced outside my machine, so, I guess, you are all safe from harm :)

看来这种行为在我的机器之外是无法复制的,所以,我猜,你们都不会受到伤害。

#2


0  

Are you sure isAfterLast evaluates to false if the cursor is before the first of 0 entries? ;) Why don't you just evaluate moveToFirst() instead? It would evaluate to false if there are no entries so the call to isAfterLast() is unnecessary anyway.

如果游标在0项中的第一个之前,您确定isAfterLast的值为false吗?,)为什么不直接计算moveToFirst()呢?如果没有条目,它的值将为false,因此对isAfterLast()的调用是不必要的。

#3


0  

rewrite that if and while into this

把它改写成这样。

try {
    if (c!=null) {
        for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
               //stuff here
        }
    }
} finally {
    if (c!=null) {
        c.close();
    }
}

#4


0  

I agree, this smells like a compiler bug. It's possible that the compiler creates a wrong jump target address in the byte code. Do you have the same problem on the emulator and device? You could add an emulator for a different phone (and different hardware architecture) to check, if this is a general problem or if it is limited to your device.

我同意,这有点像编译器的问题。编译器可能在字节代码中创建了错误的跳转目标地址。你对模拟器和设备有同样的问题吗?您可以为不同的电话(以及不同的硬件架构)添加一个仿真器来检查,如果这是一个普遍的问题,或者它仅限于您的设备。


What one could try - grab a decompiler (I'd recommend JD Java Decompiler, hoping it works for android applications too) and try to decompile the class files to see, id the decompiler result matches your source code - at least logically. If there's a big difference -> potential compiler bug -> issue report to the android development team.

可以尝试的是——获取一个反编译器(我推荐JD Java反编译器,希望它也适用于android应用程序),并尝试反编译类文件,以查看反编译器结果是否与源代码匹配——至少在逻辑上是这样。如果有很大的不同——>潜在的编译错误——>向android开发团队发布报告。

#5


0  

I believe isAfterLast is working as intended. isAfterLast will be false because there are no rows as you stated, so it can never evaluate if it is at the last row.

我相信这是最后的结果。isAfterLast将为false,因为如您所述没有行,因此它永远无法计算它是否在最后一行。

Plus in your code example above you never moved to the first row to begin with prior to calling isAfterLast(), The if statement never gets evaluated again.

在上面的代码示例中,如果在调用isAfterLast()之前从未移动到第一行,那么if语句将不再被重新评估。

use

使用

if (cursor.moveToFirst()) {
       // code
    while(cursor.isAfterLast() == false) {
        // code
     String[] columNames = cursor.getColumnNames();
     for (String column : columnNames)  {
         aRow.put(column, cursor.getString(cursor.getColumnIndex(column))); 
     }
    cursor.moveToNext();
    phones.put(aRow);

    }
}

Hope that helps.

希望有帮助。

#1


1  

It seems that this behavior cannot be reproduced outside my machine, so, I guess, you are all safe from harm :)

看来这种行为在我的机器之外是无法复制的,所以,我猜,你们都不会受到伤害。

#2


0  

Are you sure isAfterLast evaluates to false if the cursor is before the first of 0 entries? ;) Why don't you just evaluate moveToFirst() instead? It would evaluate to false if there are no entries so the call to isAfterLast() is unnecessary anyway.

如果游标在0项中的第一个之前,您确定isAfterLast的值为false吗?,)为什么不直接计算moveToFirst()呢?如果没有条目,它的值将为false,因此对isAfterLast()的调用是不必要的。

#3


0  

rewrite that if and while into this

把它改写成这样。

try {
    if (c!=null) {
        for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
               //stuff here
        }
    }
} finally {
    if (c!=null) {
        c.close();
    }
}

#4


0  

I agree, this smells like a compiler bug. It's possible that the compiler creates a wrong jump target address in the byte code. Do you have the same problem on the emulator and device? You could add an emulator for a different phone (and different hardware architecture) to check, if this is a general problem or if it is limited to your device.

我同意,这有点像编译器的问题。编译器可能在字节代码中创建了错误的跳转目标地址。你对模拟器和设备有同样的问题吗?您可以为不同的电话(以及不同的硬件架构)添加一个仿真器来检查,如果这是一个普遍的问题,或者它仅限于您的设备。


What one could try - grab a decompiler (I'd recommend JD Java Decompiler, hoping it works for android applications too) and try to decompile the class files to see, id the decompiler result matches your source code - at least logically. If there's a big difference -> potential compiler bug -> issue report to the android development team.

可以尝试的是——获取一个反编译器(我推荐JD Java反编译器,希望它也适用于android应用程序),并尝试反编译类文件,以查看反编译器结果是否与源代码匹配——至少在逻辑上是这样。如果有很大的不同——>潜在的编译错误——>向android开发团队发布报告。

#5


0  

I believe isAfterLast is working as intended. isAfterLast will be false because there are no rows as you stated, so it can never evaluate if it is at the last row.

我相信这是最后的结果。isAfterLast将为false,因为如您所述没有行,因此它永远无法计算它是否在最后一行。

Plus in your code example above you never moved to the first row to begin with prior to calling isAfterLast(), The if statement never gets evaluated again.

在上面的代码示例中,如果在调用isAfterLast()之前从未移动到第一行,那么if语句将不再被重新评估。

use

使用

if (cursor.moveToFirst()) {
       // code
    while(cursor.isAfterLast() == false) {
        // code
     String[] columNames = cursor.getColumnNames();
     for (String column : columnNames)  {
         aRow.put(column, cursor.getString(cursor.getColumnIndex(column))); 
     }
    cursor.moveToNext();
    phones.put(aRow);

    }
}

Hope that helps.

希望有帮助。