3

我知道如何通过冗长的非优雅方式完成这项任务,但我想缩短它并使其更优雅。下面我展示了我可以用非优雅的方式做什么,以及我想如何优雅地做。优雅的方式不是编译。我评论了错误的位置和错误。

任何代码结构帮助表示赞赏!先感谢您。

结果.java

public class Results extends Activity {
int x = -1;

Button q1details, q2details, q3details, q4details, q5details, q6details, q7details, q8details, q9details, q10details;

final Context context = this;

@Override
public void onCreate(Bundle savedInstanceState) {

    q1details = (Button)findViewById(R.id.q1details);
    q2details = (Button)findViewById(R.id.q2details);
    q3details = (Button)findViewById(R.id.q3details);
    q4details = (Button)findViewById(R.id.q4details);
    q5details = (Button)findViewById(R.id.q5details);
    q6details = (Button)findViewById(R.id.q6details);
    q7details = (Button)findViewById(R.id.q7details);
    q8details = (Button)findViewById(R.id.q8details);
    q9details = (Button)findViewById(R.id.q9details);
    q10details = (Button)findViewById(R.id.q10details);

    buttonList.add(q1details); buttonList.add(q2details); buttonList.add(q3details); buttonList.add(q4details); buttonList.add(q5details); buttonList.add(q6details); buttonList.add(q7details); buttonList.add(q8details); buttonList.add(q9details); buttonList.add(q10details);

    for(int i = 0; i < buttonList.size(); i++) {
        buttonList.get(i).setText("Question Details");
        buttonList.get(i).setOnClickListener(new OnClickListener() {
            public void onClick(View arg0) {
                x = i;  //ERROR:  "Cannot refer to a non-final variable  i inside an inner class defined in a different method."  But I cannot put the i as Final in a for-loop.
                displayDetails();
            }
        });
    }

/*      q1details.setOnClickListener(new OnClickListener() {
        public void onClick(View arg0) {
            x = 0;
            displayDetails();
        }
    });
            //I could do 10 of these to accomplish the task but its non-elegant...
*/

public void displayDetails() {

    final Dialog dialog = new Dialog(context);
    dialog.setContentView(R.layout.questiondetails);
    dialog.setTitle("Question " + (x + 1) + " Details");

    ImageView image = (ImageView)dialog.findViewById(R.id.image);
    TextView correctness = (TextView)dialog.findViewById(R.id.correctness);
    TextView questionHeader = (TextView)dialog.findViewById(R.id.questionHeader);
    TextView question = (TextView)dialog.findViewById(R.id.question);
    TextView selectedAnswerHeader = (TextView)dialog.findViewById(R.id.selectedAnswerHeader);
    TextView selectedAnswer = (TextView)dialog.findViewById(R.id.selectedAnswer);
    TextView correctAnswerHeader = (TextView)dialog.findViewById(R.id.correctAnswerHeader);
    TextView correctAnswer = (TextView)dialog.findViewById(R.id.correctAnswer);
    TextView points = (TextView)dialog.findViewById(R.id.points);
    TextView verseHeader = (TextView)dialog.findViewById(R.id.verseHeader);
    TextView verse = (TextView)dialog.findViewById(R.id.verse);
    Button close = (Button)dialog.findViewById(R.id.close);

    if(qs.get(x).getSelectedAnswer() == qs.get(x).getCorrectAnswer()) {
        image.setBackgroundResource(R.drawable.green_check_mark);
        correctness.setText("CORRECT!");
        correctness.setTextColor(Color.GREEN);
    } else {
        image.setBackgroundResource(R.drawable.red_x);
        correctness.setText("INCORRECT!");
        correctness.setTextColor(Color.RED);
    }

    String a = "<u>QUESTION</u>";
    questionHeader.setText(Html.fromHtml(a));
    question.setText(qs.get(0).getQuery());

    String b = "<u>ANSWER YOU SELECTED</u>";
    selectedAnswerHeader.setText(Html.fromHtml(b));
    selectedAnswer.setText("" + qs.get(0).getStringSelectedAnswer());

    String c = "<u>CORRECT ANSWER</u>";
    correctAnswerHeader.setText(Html.fromHtml(c));
    correctAnswer.setText("" + qs.get(0).getStringCorrectAnswer());

    points.setText("You received " + QuestionView.getPointsPerQuestion().get(x) + " out of a possible 100 points.");

    String d = "<u>PROVE THE ANSWER IN YOUR BIBLE</u>";
    verseHeader.setText(Html.fromHtml(d));
    verse.setText(qs.get(0).getVerse());        

    close.setText("Close");

    close.setOnClickListener(new OnClickListener() {
        public void onClick(View arg0) {
            dialog.dismiss();
        }
    });
    dialog.show();
}
4

3 回答 3

6

在匿名类的外部范围内声明的最终引用可供该匿名类访问。(Java 的闭包风格):

for(int i = 0; i < buttonList.size(); i++) {
    Button button = buttonList.get(i);
    button.setText("Question Details");

    final int j = i;

    button.setOnClickListener(new OnClickListener() {
        public void onClick(View arg0) {
            x = j;
            displayDetails();
        }
    });
}
于 2013-02-15T16:37:25.913 回答
2

里面的代码onClick()将在按下 Button 时运行,而不是在循环期间运行......所以即使你以某种方式制作ifinal,它也不会保持你期望的值。

但是,您可以使用泛型setTag()getTag()方法来存储i.
就像是:

for(int i = 0; i < buttonList.size(); i++) {
    Button button = buttonList.get(i);
    button.setTag(i);
    button.setText("Question Details");
    button.setOnClickListener(new OnClickListener() {
        public void onClick(View arg0) {
            x = (Integer) arg0.getTag();
            displayDetails();
        }
    });
}
于 2013-02-15T16:15:56.823 回答
0

您不能像这样在匿名函数中引用变量。有 3 种方法可以解决此问题。

1)在视图上使用 setTag 和 getTag 来标记它的索引号

2)不要使用匿名类。使其成为在函数外部(但在活动类内部)定义的私有类,并使其通过其构造函数获取索引。

3)在每次点击时,遍历按钮列表并找到等于传入视图的索引。

我认为 2 号是最干净的,但它们中的任何一个都可以。

于 2013-02-15T16:18:32.630 回答