Blog15 of GrrrNeko BASE

このコーナーではデベロッパー向けに、私がハマってしまったポイントとその解決法を書いていきます。

2012-10-8

android: 異なるスコープ(ブロック、スレッド)間での値の受け渡し(2) - what を使用する方法 -

症状:

 異なるスコープ(ブロック、スレッド)間での値の受け渡しができない。

 例えば、以下のようなコードを書いたとする。

int = a

final AlertDialog.Builder adb = new AlertDialog.Builder(this);
adb.setMessage("SELECT")
       .setPositiveButton("YES",
                new DialogInterface.OnClickListener() {
                         public void onClick(DialogInterface dialog, int which) {
	                a = 100;
		}
	})
        .setNegativeButton("NO",
	new DialogInterface.OnClickListener() {
	         public void onClick(DialogInterface dialog, int which) {
                                a = 200;
                                }
	})
         .show();

TextView tv = (TextView) findViewById(R.id.textview1);
tv.setText("Result: " + a);

 ここで、はじめの変数 a の宣言を final にすると alertdialog ブロック内の a に値を代入できず、かといって static にすると今度は a が参照できない、と言われてしまう。

  • final にした場合:
    • エンクロージング型に定義されているため final のローカル変数 a を代入することができません
  • static にした場合:
    • 異なるメソッドで定義されたインナー・クラス内で非 final 変数 a を参照できません

解決法:

 私が求めていた本当の解決策は、alertdialog の挙動がおかしいで記したとおりだが、解決策を求めて放浪している間に、異なるスコープ(ブロック、スレッド)間での値の受け渡しと同じ結果になるが異なる方法をいくつか発見した。

 その一つが sendemptymessage で msg.what を送る方法。

final Handler handler = new Handler() {
    public void handleMessage(Message msg) {
      	TextView tv = (TextView) findViewById(R.id.textview1);
        	tv.setText("Result: " + msg.what);
    }
};
        
final AlertDialog.Builder adb = new AlertDialog.Builder(this);
adb.setMessage("SELECT")
    .setPositiveButton("YES",
	new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
	new Thread (new Runnable() {
	    public void run() {
		handler.sendEmptyMessage(100);
	    }
                }).start();
        }
    })
    .setNegativeButton("NO",
	new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
	new Thread (new Runnable() {
	    public void run() {
		handler.sendEmptyMessage(200);
	    }
	}).start();
        }
    })
    .show();

 これはこれで完結していてそれなりに用途はあるだろうが、この方法では final の呪縛からは逃れられない。

ページトップへ