Blog17 of GrrrNeko BASE

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

2012-10-8

android: 異なるスコープ(ブロック、スレッド)間での値の受け渡し(4) - 渡さない方法 -

症状:

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

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

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


異なるスコープ(ブロック、スレッド)間での値の受け渡しにおいては、 handleMessage で送られてきたメッセージを受け取っている。これは Android Developers の handleMessage の項目に書いてある通り、メッセージを受け取るために必須だからだ。

 しかし、この場合の「同じ結果」を求めるのであれば、そもそもわざわざ送る必要がない。すなわち、AleartDialog のボタン処理 onClick(DialogInterface dialog, int which) { この部分 } で直接表示させればよく、この場合 handleMessage の件が要らなくなる。

final AlertDialog.Builder adb = new AlertDialog.Builder(this);
adb.setMessage("SELECT")
    .setCancelable(false)
    .setPositiveButton("YES",
    		new DialogInterface.OnClickListener() {
    	public void onClick(DialogInterface dialog, int which) {
    	    a = 100;
    	    final TextView tv = (TextView) findViewById(R.id.textview1);
    	    tv.setText("Result: " + a);
    	}
        })
        .setNegativeButton("NO",
    		new DialogInterface.OnClickListener() {
    	public void onClick(DialogInterface dialog, int which) {
    					
    	    a = 200;
    	  final TextView tv = (TextView) findViewById(R.id.textview1);
    	  tv.setText("Result: " + a);
   	}
    })
    .show();

 これはこれで完結しているが、上記の final の呪縛の解決策にはなっていない。

ページトップへ