36

私は6年前にこの質問をしました。その間に、Android開発のベストプラクティスが変更され、私はより優れた開発者になりました。

それ以来、onClickXML属性を使用することは悪い習慣であることに気づき、作業中のコードベースからXML属性を削除しました。

すべてのクリックハンドラーは、XMLレイアウトではなく、アプリのコードで定義されるようになりました。

使用しない理由onClick

  1. onClickXML属性の値を間違えると、実行時エラーが発生しやすくなります。
  2. 開発者は、レイアウトから呼び出されていることに気付かずに、クリックハンドラメソッドの名前をリファクタリングする可能性があります(理由1を参照)。
  3. どのメソッドが実際に呼び出されているかを見つけることは、必ずしも明白ではありません。特にレイアウトがフラグメントによって使用されている場合
  4. レイアウトと動作の問題を分離するのは良いことです。使用onClickするとそれらが混ざり合いますが、これは悪いことです。

私はあなたがレイアウトで決して使用しないことをあなたに確信させたことを望みonClickます:)!

onClick以下は私の最初の質問です。これは、使用が悪い考えである理由のかなり良い例です。

===

XMLでメニュー項目を定義していて、API 11で追加されたonClick属性を使用しようとしています。4.0.3を実行しているエミュレーターでアクティビティを起動すると、次の例外が発生します。

FATAL EXCEPTION: main
android.view.InflateException: Couldn't resolve menu item onClick handler 
    onFeedbackMenu in class android.view.ContextThemeWrapper

...
Caused by: java.lang.NoSuchMethodException: onFeedbackMenu 
    [interface com.actionbarsherlock.view.MenuItem]
at java.lang.Class.getConstructorOrMethod(Class.java:460)

アクティビティで次のメソッドが定義されているため、例外の原因がわかりません

import com.actionbarsherlock.view.MenuItem;
...
public void onFeedbackMenu( MenuItem menuItem ) { 
    Toast.makeText( this, "onFeedBack", Toast.LENGTH_LONG ).show();
}

私のXMLメニュー定義ファイルには次のものが含まれています。

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
...
    <item
        android:id="@+id/menu_feedback"
        android:icon="@drawable/ic_action_share"
        android:showAsAction="ifRoom"
        android:title="@string/menu_feedback"
        android:onClick="onFeedbackMenu" />
</menu>

下位互換性のために、ActionBarSherlockを使用しています。また、2.3.xでアプリを実行すると、非常によく似た例外が発生します。

これは、スタックトレースのより完全なバージョンです

FATAL EXCEPTION: main
android.view.InflateException: Couldn't resolve menu item onClick handler 
    onFeedbackMenu in class android.view.ContextThemeWrapper
    at com.actionbarsherlock.view.MenuInflater$InflatedOnMenuItemClickListener.<init>(MenuInflater.java:204)
    at com.actionbarsherlock.view.MenuInflater$MenuState.setItem(MenuInflater.java:410)
    at com.actionbarsherlock.view.MenuInflater$MenuState.addItem(MenuInflater.java:445)
    at com.actionbarsherlock.view.MenuInflater.parseMenu(MenuInflater.java:175)
    at com.actionbarsherlock.view.MenuInflater.inflate(MenuInflater.java:97)
    ...
Caused by: java.lang.NoSuchMethodException: onFeedbackMenu 
    [interface com.actionbarsherlock.view.MenuItem]
    at java.lang.Class.getConstructorOrMethod(Class.java:460)
    at java.lang.Class.getMethod(Class.java:915)
    at com.actionbarsherlock.view.MenuInflater$InflatedOnMenuItemClickListener.<init>(MenuInflater.java:202)
    ... 23 more
4

7 に答える 7

76

私は自分に合った解決策を見つけました。通常、onClickレイアウトの属性には次のメソッドがあります

public void methodname(View view) { 
    // actions
}

メニュー項目 (この場合は Sherlock メニュー) では、次の署名に従う必要があります。

public boolean methodname(MenuItem item) { 
    // actions
}

したがって、あなたの問題は、あなたのメソッドがvoidではなく を返すことでしbooleanた。

于 2012-09-18T22:41:05.517 に答える
16

私の場合、ブロックに含まAndroidManifest.xmlれる私のアプリケーション (デフォルトの Eclipse アシスタントによって開始されます) です。android:theme="@style/AppTheme"<application>

問題の原因をデバッグすると、行が

mMethod = c.getMethod(methodName, PARAM_TYPES);

inは、私のクラスではなく疑わしいものandroid.view.MenuInflater/InflatedOnMenuItemClickListenerで呼び出されました(もちろん、onClick ハンドラーは含まれていません)。cActivityandroid.view.ContextThemeWrapper

それで、私は を削除しandroid:theme、すべてが機能しました。

于 2013-01-14T01:42:14.990 に答える
1

私の場合、問題はメニュー XML とアクティビティの両方にあることでした。 私は実際には欠陥がありました (存在しないメソッドを指していたため) が、サポートされておらず無視されている Android 2.x でテストしていたため、最初はこれに気付きませんでした。ただし、4.x でテストすると、このエラーが発生し始めました。onClickonCreateOptionsMenuonClickonClick

基本的に、onClickAndroid 2.x での展開を計画している場合は使用しないでください。onClick3.0 以降で実行しようとするまで、値は黙って無視されます。

于 2012-09-20T22:07:59.370 に答える
0

ActionBar メニュー項目とその onClick イベントにも同じ問題があることがわかりました。私が発見したのは、私が開発しているワークステーションがメモリ不足で、再起動する必要があるということです。Android VM は、参照されているメソッド名を解決できるようになりました。

于 2012-07-01T07:10:42.357 に答える
-1
@Override
public boolean onCreateOptionsMenu(Menu menu) 
{
    getMenuInflater().inflate(R.menu.activity_main, menu);

    MenuItem item = menu.findItem(R.id.menu_open);

    if (item == null)
        return true;

    item.setOnMenuItemClickListener
    (
        new MenuItem.OnMenuItemClickListener () 
        { 
            public boolean onMenuItemClick(MenuItem item) 
            { return (showDirectory(item)); }
        } 
    ); 

    return true;
}


public boolean showDirectory (MenuItem item)
{
    CheckBox checkBox = (CheckBox) findViewById (R.id.checkBox1);
    checkBox.setChecked(true);
}
于 2012-07-01T18:08:01.883 に答える