3

私はこのタスクをエレガントではない長い方法で達成する方法を知っていますが、それを短くしてよりエレガントにしたいと思っています。以下に、私がエレガントでない方法で何ができるか、そしてそれをどのようにエレガントにやりたいかを示します。エレガントな方法はコンパイルではありません。エラーがどこで何であるかについてコメントしました。

コード構造のヘルプは大歓迎です!前もって感謝します。

Results.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()は、ループ中ではなく、ボタンが押されたときに実行されます...したがって、何らかのi方法でfinalを作成しても、期待する値は保持されません。

ただし、ジェネリック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 に答える