进入if和else语句吗?

3

我有这段代码(已更新为解决方案)。

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ...
        final Direction d = directions.get(position);
        if (d != null) {

            TextView direction = (TextView) row.getTag(R.id.directionTextView);
            TextView departure1 = (TextView) row.getTag(R.id.departure1);
            TextView departure2 = (TextView) row.getTag(R.id.departure2);
            TextView departure3 = (TextView) row.getTag(R.id.departure3);

            direction.setText(d.getName());

            if (d.getTimeStamps().size() == 0) {
                departure1.setText(R.string.nodepartures);
                departure1.setTextColor(R.color.grey);
            } else {
                for (int i = 0; i < d.getTimeStamps().size(); i++) {
                    switch (i) {
                    case 0:
                        departure1.setText(d.getTimeStamps().get(i));
                        break;
                    case 1:
                        departure2.setText(d.getTimeStamps().get(i));
                        break;
                    case 2:
                        departure3.setText(d.getTimeStamps().get(i));
                        break;
                    default:
                        break;
                    }
                }
            }
        }
        return row;
    }
}

我遇到的问题是其中一个TextView在不应该变灰时会变灰。我尝试通过将文本始终设置回黑色来修复它,但这样会使每一个TextView都变灰。直到我尝试了以下方法:
setTextColor(context.getResources().getColor(R.color.black));

不仅仅是

setTextColor(R.color.black);

不知道为什么将文本设置为灰色时后者起作用,但就是这样。我想我可能有点儿迟钝。 :)

4
记住,在这种情况下,几乎从来不是由于 Android 或 Java 的问题。 - naikus
19
循环 for(i ..) 中使用了 switch(i) 语句。 - quantumSoup
2
也许提供一些关于这段代码的背景会有所帮助。没有上下文,我只能告诉你在Android中if-else块确实正常工作。 - Andrzej Doyle
1
好的,根据上下文(我们并不知道),您可以将departureX变量放入一个数组中,然后使用 departures[i].setText() - Jake
我只是想知道,当您调试此代码并逐步执行时,它会同时进入if和else吗? - Rabas
显示剩余8条评论
7个回答

3
你认为正在发生的事情根本不可能发生(*,**)。你需要做的是证明它没有发生。我会通过在代码中添加一些跟踪打印来实现这一点。在if语句之前放置一个跟踪打印,在“then”和“else”子句的开头放置一个跟踪打印,在if语句之后放置一个跟踪打印。然后运行它。我预计这将揭示if语句实际上被运行了两次,并且第一次运行“then”子句,第二次运行“else”子句。
(*理论上,如果模拟器中存在严重的错误,可能会发生。但只有在您有不可辩驳的证据时才应考虑这种可能性。)
(**另一个可能性是样例代码与您正在测试的实际代码之间可能存在显着差异。这种情况确实会发生...)

我已经做过了。这证明它并没有发生,所以我猜我在某些数字上是黑色/灰色色盲?也许这是共感现象!我在原帖中附上了一个图片链接。 :P - AmITheRWord

2
AsLanFromNarnia在正确的道路上。ListView回收其子视图。您永远不能假设convertView处于其类型的任何默认状态。每次调用getView时都设置每个相关字段。在您的情况下,这意味着在设置文本时设置文本颜色。
处理此类希望具有异构列表的情况还有另一种方法:使用视图类型。您的适配器可以返回您拥有的类型数量以进行getViewTypeCount,然后从getItemViewType报告每个项目的类型。如果这样做,您将始终获得传递到您的getView方法中的正确类型的convertView,减轻了每次更改静态布局的需要。

我不会感到惊讶,如果他第一次尝试将其明确设置为黑色时出现了拼写错误。我进一步评论说,他应该尝试将其设置为一些颜色,比如红色,但不幸的是他还没有回复我们。他附带的屏幕截图中有一个灰色字段和两个黑色字段,这使得它似乎很难相信这是任何模拟器问题,而只是关于TextView对象生命周期的误解。 - Fredrick Pennachi
我尝试将它设置为红色,但它仍然变成了灰色。但是当我在之前添加了上下文内容后,它就起作用了!所以...可能只是忽略了一些小细节,让我陷入了困境。我编辑了原始内容,只包括有问题的代码和解决方案。谢谢! :) - AmITheRWord
是的,那样就可以了。:) 在R中,资源ID值是自动生成的整数。看起来你使用的ID在解释为打包的ARGB值时会转换成灰色阴影。 - adamp

0

我同意Aircule的观点!这段代码相当疯狂!换成这个怎么样?

if(d.getTimeStamps().isEmpty())
{
   departure1.setText(R.string.nodepartures);
   departure1.setTextColor(R.color.grey);
} 
else
{
   departure1.setText(d.getTimeStamps().get(0));
   departure2.setText(d.getTimeStamps().get(1));
   departure3.setText(d.getTimeStamps().get(2));
}

它应该做完全相同的事情,而且要简单得多。另外,假设您运行此代码一次并且列表为空,因此将departure1的颜色设置为灰色并再次运行它。这次您获取数据并填充项目,但从未更改departure1的颜色,因此它将保持灰色。同样,如果您以相反的方式采取该场景,则在列表为空时不清空 TextViews 。另一个提示是,如果只会有三个项目(或任何小的固定数量的项目),那么最好使用普通布局而不是列表。这样,您就不必制作自定义适配器,只需按名称调用项目即可。


2
嗯,不太确定这是否完全相同,如果ArrayList只包含1个项目怎么办? - Jake
ArrayList可以包含从0到3个项目,具体取决于正在检查的行。您的代码会使我的应用程序崩溃。如果我运行此代码一次,并且该特定行的列表为空,则再次运行代码时它仍将为空。该列表永远不会被修改。我将尝试更新我的代码示例以提供更多上下文。 - AmITheRWord
在这种情况下,我仍然建议放弃使用 List,而只是使用一个 LinearLayout - CaseyB
这将会增加很多额外的代码,使用嵌套的for循环动态添加子视图,而适配器会为我处理。我还需要用ScrollView包围LinearLayout。如果其他方法都失败了,我会尝试这个,但我真的不想再花一个小时在这上面了。 - AmITheRWord

0

根据您的描述,我们最多只能给出一些提示。

  • 您确定重新编译了所有代码吗?我曾经看到过调试产生有趣结果的情况,因为部分代码与正在调试的字节码不同步
  • 这是一个基于事件的系统吗?您的代码被调用两次,一次是空列表,紧接着是添加条目后的列表,可能是这个原因吗?

作为代码改进,我会对switch进行重构(这里的假设是控制类型是Text,这可能是错误的,但很容易修复):

if (d.getTimeStamps().isEmpty()) {
   departure1.setText(R.string.nodepartures);
   departure1.setTextColor(R.color.grey);
} else {
    Text[] fields = new Text[] { departure1, departure2, departure3 };

    for (int i = 0; i < fields.length && i < d.getTimeStamps().size(); i++) {
        fields[i].setText(d.getTimeStamps().get(i));
        fields[i].setTextColor(R.color.black);
    }
}

更新

看到您没有为出发值设置颜色,我认为您假设这些行在代码运行时是新创建的。如果这个假设不正确,那么您的情况可能是之前曾经显示“无出发”的行现在被重复使用来显示出发信息,因此继承了灰色。


感谢您提供具体的改进建议。我尝试了清理和重建项目,甚至重新启动了Eclipse和模拟器,但仍然没有运气。我已经更新了原始帖子,并附上了适配器的完整源代码。我看不出有什么问题,但像naikus建议的那样,我可能在这个时候对代码视而不见。我希望有人能够发现其中的错误。 - AmITheRWord

0

我相信它变灰是因为在程序的某个点上,该方法被调用时时间戳为0。

只需要发生一次就可以设置departure1.textColor属性,然后它将持续到改变回来为止。

你提到尝试在else语句中将其设置为黑色,但结果所有东西都变成了灰色。这根本没有意义。尝试在每个case语句中添加将文本转换为黑色的命令,例如:

case 0:
departure1.setTextColor(R.color.black);
departure1.setText(d.getTimeStamps().get(i));
break;
case 1:
departure2.setTextColor(R.color.black);
departure2.setText(d.getTimeStamps().get(i));
break;
case 2:
departure3.setTextColor(R.color.black);
departure3.setText(d.getTimeStamps().get(i));
break;

是的,这会将每个TextView都变成灰色。 :P - AmITheRWord
你尝试过其他颜色,比如红色之类的吗?只是为了检查一下? - Fredrick Pennachi

0
嗯...我看不出这样会发生。你确定括号放得正确吗?如果你把语句调换一下,它还是会出错吗?

我相信我的括号放置得很正确,但我已经在原帖中更新了适配器的完整源代码。我可能现在有点看不懂代码。 - AmITheRWord

0
你在layout XML文件中设置了默认颜色或样式,这些文件由LayoutInflator加载了吗?

不,我没有。我应该尝试在XML布局中将颜色设置为黑色吗? - AmITheRWord

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接