以下のメッセージと共に、java.lang.IllegalStateException例外が発生しました。
「Could not find a method buttonClick(View) in the activity」
その時はOnClickListenerを実装した方が早かったので、深く調べなかったのですが、
たまたま思い出したので調べてみました。
※今回はAndroid2.2のソースコードを追いかけました。1.6でも同様の現象に
ぶち当たるのではないかと思います。
実際、レイアウトXMLのOnClickが設定される場所は、Viewクラスにあります。
case R.styleable.View_onClick: if (context.isRestricted()) { throw new IllegalStateException("The android:onClick attribute cannot " + "be used within a restricted context"); } final String handlerName = a.getString(attr); if (handlerName != null) { setOnClickListener(new OnClickListener() { private Method mHandler; public void onClick(View v) { if (mHandler == null) { try { mHandler = getContext().getClass().getMethod(handlerName, View.class); } catch (NoSuchMethodException e) { int id = getId(); String idText = id == NO_ID ? "" : " with id '" + getContext().getResources().getResourceEntryName( id) + "'"; throw new IllegalStateException("Could not find a method " + handlerName + "(View) in the activity " + getContext().getClass() + " for onClick handler" + " on view " + View.this.getClass() + idText, e); } } try { mHandler.invoke(getContext(), View.this); } catch (IllegalAccessException e) { throw new IllegalStateException("Could not execute non " + "public method of the activity", e); } catch (InvocationTargetException e) { throw new IllegalStateException("Could not execute " + "method of the activity", e); } } }); } break;
handlerName変数には呼び出されるはずのメソッド名が設定されています。
ポイントは、以下のコードになります。
mHandler = getContext().getClass().getMethod(handlerName,
View.class);
この部分で、クラス内にOnClickで設定したメソッドがあるかどうかを確認しています。
さて、今回の現象はActivityだとメソッドが発見できて、Dialogだと発見出来ないわけですから、getContext().getClass()で返されるクラスのインスタンスが違ってそうな気がします。
ということで、Dialog#onCreate(setContentView()を呼び出した直後)で
Log.d("TEST", "ClassName = " + getContext().getClass().getName());
なんてことをしてみました。
すると、出力されたログをみると、
ClassName = android.view.ContextThemeWrapper
と出力されました。
Activityだと同じ事ができないのですが、恐らく、getContext()がActivityのインスタンスを返すのだろうと思われます。
Activityのインスタンスであれば、自分で実装してあれば、メソッドが発見できますが、DialogでgetContext()するとContextThemeWrapperが返ってくるため、
OnClickのメソッドが発見出来ないわけです。
ちなみに、Dialog#getContext()が返す、Contextは、以下の通りです。
mContext = new ContextThemeWrapper( context, theme == 0 ? com.android.internal.R.style.Theme_Dialog : theme); public final Context getContext() { return mContext; }
ということで、結論は、「DialogではレイアウトXMLのOnClickは使えない」と言うことがわかりました。
DialogではおとなしくOnClickListenerを実装しましょう。
0 件のコメント:
コメントを投稿