2013年12月26日木曜日

ActionBarActivityで finalになったonMenuItemSelectedのソースを追ってみた

ActionBarActivity#onOptionsItemSelectedのソースを追ってみた。

android.support.v7.app.ActionBarActivity
  1. ActionBarActivityDelegate mImpl;  
  2.   
  3. @Override  
  4. public final boolean onMenuItemSelected(int featureId, android.view.MenuItem item) {  
  5.     if (mImpl.onMenuItemSelected(featureId, item)) {  
  6.         return true;  
  7.     }  
  8.   
  9.     final ActionBar ab = getSupportActionBar();  
  10.     if (item.getItemId() == android.R.id.home && ab != null &&  
  11.             (ab.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0) {  
  12.         return onSupportNavigateUp();  
  13.     }  
  14.     return false;  
  15. }  
5行目で、ActionBarActivityDelegateのonMenuItemSelectedを呼び出している。
ActionBarActivityDelegateを実装は幾つかのOSレベル毎に分かれているので、 その1つActionBarActivityDelegateBaseを見てみる。

android.support.v7.app.ActionBarActivityDelegateBase
  1. @Override  
  2. public boolean onMenuItemSelected(int featureId, MenuItem item) {  
  3.     if (featureId == Window.FEATURE_OPTIONS_PANEL) {  
  4.         item = MenuWrapperFactory.createMenuItemWrapper(item);  
  5.     }  
  6.     return mActivity.superOnMenuItemSelected(featureId, item);  
  7. }  
ActionBarActivityのsuperOnMenuItemSelectedを呼んでいる。

android.support.v7.app.ActionBarActivity
  1. boolean superOnMenuItemSelected(int featureId, MenuItem menuItem) {  
  2.     return super.onMenuItemSelected(featureId, menuItem);  
  3. }  
ActionBarActivityの親クラスFragmentActivityのonMenuItemSelectedを呼んでいる。

android.support.v4.app.FragmentActivity
  1. /** 
  2.  * Dispatch context and options menu to fragments. 
  3.  */  
  4. @Override  
  5. public boolean onMenuItemSelected(int featureId, MenuItem item) {  
  6.     if (super.onMenuItemSelected(featureId, item)) {  
  7.         return true;  
  8.     }  
  9.       
  10.     switch (featureId) {  
  11.         case Window.FEATURE_OPTIONS_PANEL:  
  12.             return mFragments.dispatchOptionsItemSelected(item);  
  13.               
  14.         case Window.FEATURE_CONTEXT_MENU:  
  15.             return mFragments.dispatchContextItemSelected(item);  
  16.   
  17.         default:  
  18.             return false;  
  19.     }  
  20. }  
6行目の親クラスActivityActivityのonMenuItemSelectedを呼んでいる。
メニューが処理されなかったら、Fragmentのメニューを呼び出している。
  • Window.FEATURE_OPTIONS_PANEL - ActionBarや昔のメニューパネル
  • Window.FEATURE_CONTEXT_MENU - ロングタップで表示されるコンテキストメニュー


android.app.Activity
  1. public boolean onMenuItemSelected(int featureId, MenuItem item) {  
  2.     CharSequence titleCondensed = item.getTitleCondensed();  
  3.   
  4.     switch (featureId) {  
  5.         case Window.FEATURE_OPTIONS_PANEL:  
  6.             // Put event logging here so it gets called even if subclass  
  7.             // doesn't call through to superclass's implmeentation of each  
  8.             // of these methods below  
  9.             if(titleCondensed != null) {  
  10.                 EventLog.writeEvent(500000, titleCondensed.toString());  
  11.             }  
  12.             if (onOptionsItemSelected(item)) {  
  13.                 return true;  
  14.             }  
  15.             if (mFragments.dispatchOptionsItemSelected(item)) {  
  16.                 return true;  
  17.             }  
  18.             if (item.getItemId() == android.R.id.home && mActionBar != null &&  
  19.                     (mActionBar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0) {  
  20.                 if (mParent == null) {  
  21.                     return onNavigateUp();  
  22.                 } else {  
  23.                     return mParent.onNavigateUpFromChild(this);  
  24.                 }  
  25.             }  
  26.             return false;  
  27.               
  28.         case Window.FEATURE_CONTEXT_MENU:  
  29.             if(titleCondensed != null) {  
  30.                 EventLog.writeEvent(500001, titleCondensed.toString());  
  31.             }  
  32.             if (onContextItemSelected(item)) {  
  33.                 return true;  
  34.             }  
  35.             return mFragments.dispatchContextItemSelected(item);  
  36.   
  37.         default:  
  38.             return false;  
  39.     }  
  40. }  
メニューは、12行目でonOptionsItemSelectedを呼び出し。 コンテキストメニューは、32行目でonContextItemSelectedを呼び出し。


リファレンスのOnMenuItemSelectedの記述
Default implementation of onMenuItemSelected(int, MenuItem) for activities. This calls through to the new onOptionsItemSelected(MenuItem) method for the FEATURE_OPTIONS_PANEL panel, so that subclasses of Activity don't need to deal with feature codes.

この通り、onOptionsItemSelectedをオーバーライドしてメニューの処理を実装を行なうのが正しいようだ。

コンテキストメニューはonContextItemSelectedをオーバーライドして処理を実装を行なうのが正しいようだ。


Honycombから、Activity#onMenuItemSelectedにはFragmentやActionBarのメニュー処理が行なわれてるためオーバーライドは注意が必要。

0 件のコメント:

コメントを投稿