2012-06-12 164 views
7

這裏的時候,打了兩次電話是一個簡單的Android應用我創建證明我的問題:安卓onCreateOptionsMenu恢復狀態

public class OptionMenuTest extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     Log.d("test", "create activity"); 
     setContentView(R.layout.options_layout); 
     if(getFragmentManager().findFragmentByTag("frag") == null) { 
      getFragmentManager().beginTransaction().add(R.id.option_fragment_container, new OptionMenuFragment(), "frag").commit(); 
     } 

    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
     Log.d("test", "saving Activity state"); 
     super.onSaveInstanceState(outState); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     Log.d("test", "create Activity options menu"); 
     menu.add("activity"); 
     return true; 
    } 
} 

片段:

public class OptionMenuFragment extends Fragment { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     Log.d("test", "create fragment"); 
     setHasOptionsMenu(true); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     TextView tv = new TextView(getActivity()); 
     tv.setText("Hello world"); 
     Log.d("test", "create fragment view"); 
     return tv; 
    } 

    @Override 
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 
     menu.add("fragment"); 
     Log.d("test", "create fragment options menu"); 
    } 
} 

佈局只是轉儲片段導入的LinearLayout :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/option_fragment_container" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    > 
</LinearLayout> 

很簡單吧?當我運行它,我得到以下輸出預期:

06-12 15:42:51.415: D/test(957): create activity 
06-12 15:42:51.446: D/test(957): create fragment 
06-12 15:42:51.446: D/test(957): create fragment view 
06-12 15:42:51.446: D/test(957): create Activity options menu 
06-12 15:42:51.446: D/test(957): create fragment options menu 

現在,當我旋轉手機,我得到一些奇怪的行爲:

06-12 15:43:11.251: D/test(957): saving Activity state 
06-12 15:43:11.290: D/test(957): create fragment 
06-12 15:43:11.290: D/test(957): create activity 
06-12 15:43:11.306: D/test(957): create fragment view 
06-12 15:43:11.306: D/test(957): create Activity options menu 
06-12 15:43:11.306: D/test(957): create fragment options menu 
06-12 15:43:11.306: D/test(957): create Activity options menu 
06-12 15:43:11.306: D/test(957): create fragment options menu 

爲什麼活動onCreateOptionMenu和片段onCreateOptionsMenu叫了兩聲?如果我刪除片段中的選項菜單,我得到1調用活動onCreateOptionsMenu預期:

06-12 15:50:03.610: D/test(1076): create fragment 
06-12 15:50:03.610: D/test(1076): create fragment view 
06-12 15:50:03.813: D/test(1076): create Activity options menu 
06-12 15:50:08.392: D/test(1076): saving Activity state // <-- rotate happens here 
06-12 15:50:08.446: D/test(1076): create fragment 
06-12 15:50:08.446: D/test(1076): create activity 
06-12 15:50:08.462: D/test(1076): create fragment view 
06-12 15:50:08.470: D/test(1076): create Activity options menu 

我不明白這一點,並沒有其他人似乎也遇到了這個問題。真正的問題是我的SearchView無法在配置更改(電話旋轉)時恢復它的狀態,因爲onCreateOptionMenu被調用兩次。第一次它似乎有它的狀態,但第二次它被清除並重置。我無法弄清楚我做錯了什麼。

在此先感謝。

+0

我覺得你最好的拍攝是獲得源代碼的保持,並通過它與調試步驟。可能是Android中的一個錯誤。 –

+0

我在這個問題上還沒有取得任何進展。我已經介紹了代碼,但不熟悉幕後的片段/活動生命週期,以瞭解正在發生的事情或可能出現的問題。現在我已經有了一個解決方法,這很「黑客」,但我正在繼續前進。如果有人想出答案,請告訴我。謝謝! – Dave

+0

我有完全相同的問題。 'onCreateOptionMenu'和'onPrepareOptionsMenu'被調用兩次,第二次重置菜單狀態。還沒有找到解決方案:( –

回答

5

我想我找到了這個問題的答案。

看看一個這樣的:

https://stackoverflow.com/a/7225296/48468

這個問題似乎是相關的事實,Android不破壞片段當活動被銷燬(當設備旋轉)。

基本上我說:

setRetainInstance(true); 

我的片段構造,問題解決了去。

希望它能幫助!

+3

是的!非常感謝你,這解決了我的問題 有趣的是,如果片段參與選項菜單並且不調用setRetainInstance(true) ,即使SearchView是由Activity添加的,如果從片段中刪除setHasOptionsMenu,活動SearchView的行爲會正常,我認爲是因爲新添加的片段導致再次調用onCreateOptionsMenu活動。 – Dave

2

@Gerardo Contijoch答案是誤導性的,除了一個事實:

在您的例子都ActivityFragment得到在旋轉時被破壞並重新創建。 這就是爲什麼onCreateOptionsMenu()被調用兩次。這是正確的和預期的行爲。

通過setRetainInstance(true)你告訴的Android不破壞片段。這在無UI的片段不支持Activity的情況下可能證明是有用的(對於AsyncTasks協調和一些其他類似服務的東西有用)。

在其他情況下,這個分片可能會導致內存泄漏,你要避免。

0

我剛纔清除菜單充氣前和工作

@Override 
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 
     menu.clear(); 
     inflater.inflate(R.menu.call_menu, menu); 
     super.onCreateOptionsMenu(menu, inflater); 

}