2012-06-28 9 views
31

Definiuję elementy menu w XML i próbuję użyć atrybutu onClick, który został dodany w interfejsie API 11. Kiedy działanie jest uruchamiane w emulatorze z wersją 4.0.3, następującymi wyjątkami wystąpić:InflateException: Nie można rozstrzygnąć pozycji menu onClick handler

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) 

ja nie rozumiem, co jest przyczyną wyjątku, ponieważ następujący sposób definiuje się w mojej działalności

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

Moja definicja menu plik XML zawiera:

<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> 

W celu zapewnienia kompatybilności wstecz używam ActionBarSherlock, a także uzyskuję bardzo podobny wyjątek po uruchomieniu aplikacji w wersji 2.3.x.

To jest bardziej kompletna wersja stosu prześledzić

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 
+1

Mam ten sam problem i wydaje się, że jest on związany z zastosowaniem niestandardowego motywu w ActionBarSherlock, ale nie jestem pewien ... Czy używasz niestandardowego motywu? – Zharf

+0

Tak, używam niestandardowego motywu. –

+1

Tak, to się dzieje dla mnie na prawdziwym urządzeniu 4.0.3, ale nie w emulatorze 4.1. Mogę tylko założyć, że to błąd w systemie Android, który został naprawiony. Nie używam ActionBarSherlock. – Timmmm

Odpowiedz

0

Okazało się, że miałem ten sam problem z elementów menu ActionBar i ich zdarzeń onclick. Odkryłem, że na stacji roboczej, w której pracuję, zabrakło pamięci i trzeba było zrestartować komputer. Android VM jest teraz w stanie rozwiązać nazwę metody, do której się odwołuje.

+0

Aktualizacja, po ponownym uruchomieniu komputera, nie zdawałem sobie sprawy, że maszyna wirtualna Androida, która pojawiła się, to 2.3.3. Jednak gdy specjalnie wybrałem, że Android VM ma być 4.0.3, nadal otrzymuję błąd dla onClick. – user1418015

+0

Znalazłem odpowiedź, która może ci pomóc (lub przynajmniej innym) ... – user1418015

+0

@Override public boolean onCreateOptionsMenu (menu menu) { getMenuInflater(). Inflate (R.menu.activity_main, menu); MenuItem item = menu.findItem (R.id.menu_open); jeśli (pozycja == null) \t return true; item.setOnMenuItemClickListener ( \t \t nowy MenuItem.OnMenuItemClickListener() \t \t { \t \t public boolean onMenuItemClick (pozycja MenuItem) \t \t \t {return (showDirectory (pozycja));}} \t \t ) ; return true; } – user1418015

0
@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); 
} 
+0

na podstawie tego wątku .. http://stackoverflow.com/questions/6150080/set-a-menu-item-as-checked-from-code .. sugeruje się, aby programiści aktualizowali menu za pomocą menu.findItem () vs findItemById(). Aby to osiągnąć, opcja menu jest utrzymywana w menu onCreateOptionsMenu lub onPrepareOptionsMenu .. omawianym tutaj .. http://developer.android.com/guide/topics/ui/menus.html – user1418015

+0

Inna rzecz, o której myślę, że dzieje się z plik XML jest taki, że pole onClick nie może zostać rozwiązane na podstawie metody spełniającej odpowiednie kryteria ... powinno to być albo ... public void [eventName] (element MenuItem) {} lub public boolean [eventName] (element MenuItem) {}. Wydaje się jednak, że nie działa. – user1418015

68

Znalazłem rozwiązanie, które zadziałało dla mnie. Zazwyczaj atrybut w układzie onClick ma następującą metodę

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

na element menu (w tym przypadku menu Sherlocka) należy postępować zgodnie z następującą sygnaturę:

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

Więc problem było to, że Twoja metoda zwróciła void, a nie boolean.

1

W moim przypadku problem polegał na tym, że miałem zarównoonClick w moim menu XML i onCreateOptionsMenu w mojej Aktywności. Moje onClick było rzeczywiście wadliwe (ponieważ wskazywało na nieistniejące metody), ale początkowo tego nie zauważyłem, ponieważ testowałem w systemie Android 2.x, gdzie onClick nie jest obsługiwane i ignorowane. Kiedyś jednak testowałem 4.x, zacząłem dostawać ten błąd.

Zasadniczo nie należy używać onClick, jeśli planujesz wdrażanie w systemie Android 2.x. Będzie cicho ignorować wartości onClick, dopóki nie spróbujesz uruchomić w wersji 3.0+.

+0

Matt, czy używasz ABS? –

+0

Nie. Co to jest ABS? –

+0

ActionBarSherlock –

16

W moim przypadku AndroidManifest.xml z mojej aplikacji (uruchamiany przez domyślnego asystenta Eclipse) zawierał android:theme="@style/AppTheme" w bloku <application>.

Gdy debugowanie przyczyny problemu, okazało się, że linia

mMethod = c.getMethod(methodName, PARAM_TYPES); 

w android.view.MenuInflater/InflatedOnMenuItemClickListener nazwano z c nie jest moja klasa Activity ale wątpliwe android.view.ContextThemeWrapper (co oczywiście nie zawierają onClick treser).

Usunąłem android:theme i wszystko działało.

+2

Ten jest interesujący, ponieważ wygląda na to, że był przyczyną mojego problemu. Jednak każdy, kto potrzebuje (lub chce) zestawu motywów, zakończyłby się tym problemem (w interfejsie API 14/15, a nie w API 16+). Dlatego moim rozwiązaniem było zlikwidowanie przypisania onClick i po prostu dodanie wywołań do metody onOptionsItemSelected(). – lilbyrdie

8

Chociaż jest to nieco nieaktualne, oto przyczyna wyjątku. Kiedy patrzysz w źródłach Androida API 15 (4.0.3-4.0.4) w klasie MenuInflater widać tą metodą:

public InflatedOnMenuItemClickListener(Context context, String methodName) { 
mContext = context; 
Class<?> c = context.getClass(); 
try { 
    mMethod = c.getMethod(methodName, PARAM_TYPES); 
} catch (Exception e) { 
    InflateException ex = new InflateException(
      "Couldn't resolve menu item onClick handler " + methodName + 
      " in class " + c.getName()); 
    ex.initCause(e); 
    throw ex; 
} 

To był wyjątek dzieje, jak Junique już zauważył. Jednak usunięcie motywu aplikacji jest tylko obejściem i nie ma prawdziwej opcji. Jak widzimy, metoda próbuje znaleźć metodę Callback w klasie przekazywanego elementu kontekstowego. Dlatego zamiast wywoływać getMenuInflater() w onCreateOptionsMenu należy wywołać new MenuInflater(this), aby this został przekazany jako kontekst, a następnie kod zadziała.

Można nadal używać getMenuInflater() dla innych wersji api, jeśli wystarczy użyć instrukcji if tak:

if (Build.VERSION.SDK_INT > 15) 
     inflater = getMenuInflater(); 
    else 
     inflater = new MenuInflater(this); 

ja właściwie nie wiem, czy błąd pojawia się w wersji api poniżej 15 też, więc po prostu ogólnie używana wersja zapisu.

Powiązane problemy