2013-04-28 37 views
10

我有這個奇怪的問題,其中我的列表片段創建了兩次,一次是在父活動上調用super.oncreate並且一次在同一父活動上調用setContentView時。這是一個簡單的應用程序,我使用不同的肖像和橫向佈局。在定位更改上創建了兩次android片段

這裏是主要的活動:

private HeadlinesFragment headlines; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    Log.w("MainActivity", "Before super.onCreate: " + this.toString()); 
    super.onCreate(savedInstanceState); 
    Log.w("MainActivity", "Before setContentView: " + this.toString()); 
    setContentView(R.layout.news_articles); 

    //check to see if its portrait 
    if (findViewById(R.id.fragment_container) != null) { 
     if(getSupportFragmentManager().findFragmentById(R.id.fragment_container) == null) { 
      headlines = new HeadlinesFragment(); 
      getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, headlines).commit(); 
     } 
    } 
} 

這裏是在佈局,土地文件夾中的news_articles:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:orientation="horizontal" 
android:layout_width="match_parent" 
android:layout_height="match_parent"> 

<fragment android:name="com.example.android.fragments.HeadlinesFragment" 
      android:id="@+id/headlines_fragment" 
      android:layout_weight="1" 
      android:layout_width="0dp" 
      android:layout_height="match_parent" /> 

<fragment android:name="com.example.android.fragments.ArticleFragment" 
      android:id="@+id/article_fragment" 
      android:layout_weight="2" 
      android:layout_width="0dp" 
      android:layout_height="match_parent" /> 

這裏是在佈局文件夾中的news_articles(對於縱向)

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

這裏是headlinesfragment這就是被創建兩次

public class HeadlinesFragment extends ListFragment { 
OnHeadlineSelectedListener mCallback; 

// The container Activity must implement this interface so the frag can deliver messages 
public interface OnHeadlineSelectedListener { 
    /** Called by HeadlinesFragment when a list item is selected */ 
    public void onArticleSelected(int position); 
} 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    Log.w("HeadlinesFragment", "inside onCreate: " + this.toString()); 

    // We need to use a different list item layout for devices older than Honeycomb 
    int layout = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? 
      android.R.layout.simple_list_item_activated_1 : android.R.layout.simple_list_item_1; 

    // Create an array adapter for the list view, using the Ipsum headlines array 
    setListAdapter(new ArrayAdapter<String>(getActivity(), layout, Ipsum.Headlines)); 
} 

@Override 
public void onStart() { 
    super.onStart(); 

    // When in landscape layout, set the listview to highlight the selected list item 
    // (We do this during onStart because at the point the listview is available.) 
    if (getFragmentManager().findFragmentById(R.id.article_fragment) != null) { 
     getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); 
    } 
} 

@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity); 

    // This makes sure that the container activity has implemented 
    // the callback interface. If not, it throws an exception. 
    try { 
     mCallback = (OnHeadlineSelectedListener) activity; 
    } catch (ClassCastException e) { 
     throw new ClassCastException(activity.toString() 
       + " must implement OnHeadlineSelectedListener"); 
    } 
} 


@Override 
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 
    // TODO Auto-generated method stub 
    super.onCreateOptionsMenu(menu, inflater); 
} 

@Override 
public void onDestroy() { 
    Log.w("HeadlinesFragment", "inside onDestroy: " + this.toString()); 
    super.onDestroy(); 
} 
} 

這裏是articlefragment

public class ArticleFragment extends Fragment { 
final static String ARG_POSITION = "position"; 
int mCurrentPosition = 0; 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
    Bundle savedInstanceState) { 
    Log.w("ArticleFragment", "inside onCreateView: " + this.toString()); 

    if (savedInstanceState != null) { 
     mCurrentPosition = savedInstanceState.getInt(ARG_POSITION); 
    } 

    // Inflate the layout for this fragment 
    View view = inflater.inflate(R.layout.article_view, container, false); 
    return view; 
} 

@Override 
public void onStart() { 
    super.onStart(); 
    Bundle args = getArguments(); 
    if (args != null) { 
     // Set article based on argument passed in 
     updateArticleView(args.getInt(ARG_POSITION)); 
    } else if (mCurrentPosition != -1) { 
     // Set article based on saved instance state defined during onCreateView 
     updateArticleView(mCurrentPosition); 
    } 
} 

@Override 
public void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 

    // Save the current article selection in case we need to recreate the fragment 
    outState.putInt(ARG_POSITION, mCurrentPosition); 
} 

@Override 
public void onDestroy() { 
    Log.w("ArticleFragment", "inside onDestroy: " + this.toString()); 
    super.onDestroy(); 
} 

}

詳細問題是這樣的:

1)啓動應用程序縱向方向 2)調用setContentView並加載news_articles,但它帶有frag的一個ment_container。 3)headlinesfragment創建//到目前爲止正常行爲 4)改變方向爲橫向 5)mainActivity被破壞 - > headlinefragment被破壞 6)上mainactivity super.oncreate稱爲 7)Headlinefragment創建 8)的setContentView在主要活動被稱爲 9)另一個標題片段被創建//問題

我已經放置日誌,可以在上面的代碼中看到,這裏是當我在縱向模式中啓動應用程序,我改變爲風景的輸出。

W/MainActivity(6925): Before super.onCreate: [email protected] 
W/MainActivity(6925): Before setContentView: [email protected] 
W/HeadlinesFragment(6925): inside onCreate: HeadlinesFragment{41d8d4d8 #0 id=0x7f050001} 
W/MainActivity(6925): inside onDestroy: [email protected] 
W/HeadlinesFragment(6925): inside onDestroy: HeadlinesFragment{41d8d4d8 # 0id=0x7f050001} 
W/MainActivity(6925): Before super.onCreate: [email protected] 
W/HeadlinesFragment(6925): inside onCreate: HeadlinesFragment{41ea7290 #0 id=0x7f050001} 
W/MainActivity(6925): Before setContentView: [email protected] 
W/HeadlinesFragment(6925): inside onCreate: HeadlinesFragment{41eb1f30 #1 id=0x7f050002} 
W/ArticleFragment(6925): inside onCreateView: ArticleFragment{41eb5f20 #2 id=0x7f050003} 

我希望我已經與我的代碼和日誌清楚,在我看來super.oncreate和的setContentView都創建一個每一個headlinesfragment;至少我想。

我的問題是爲什麼會創建2個headlinesfragment實例,以及我如何避免這種情況。

,瞭解關於此次

回答

15

在你活動的onCreate任何幫助非常感謝,您可以檢查savedInstanceState捆綁的狀態。如果它不爲空,則表示發生了配置更改(在您的情況下,屏幕方向更改),並且您不需要重新創建Fragment

您正在做的另一個錯誤是您試圖檢索FragmentfindFragmentById。不是傳遞片段ID,而是給予它附加到片段的視圖的ID,這是不同的(這就是我猜測這總是返回null的原因)。

正確實現的會更喜歡這個(這是你的Activity):

//check to see if its portrait 
    if (findViewById(R.id.fragment_container) != null) { 
     if(savedInstanceState == null) { 
      headlines = new HeadlinesFragment(); 
      getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, headlines, FRAGMENT_TAG_STRING).commit(); // Use tags, it's simpler to deal with 
     } else { 
      headlines = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG_STRING); 
     } 
    } 
+0

感謝您的迴應,但是問題在於應用程序轉向橫向時,您所提供的代碼仍然無法執行。另外關於你給出的代碼,當應用程序第一次以縱向模式啓動時,savedInstanceState爲null,else塊被執行,所以如果我們從來沒有創建它,我們如何通過標記找到HeadlinesFragment? – 2013-05-12 16:03:50

+3

我認爲如果陳述條件是倒退在這裏。如果存在已保存的實例狀態,則應找到現有片段。如果保存的實例狀態爲空,則應該創建一個新的片段。 – Razz 2015-04-09 15:24:40

+0

@Razz是正確的。注意:如果savedInstanceState IS爲null,那麼您創建一個新的片段,否則片段已經存在!所以,只要將內部if語句更改爲if(savedInstanceState == null) – 2015-11-08 00:07:52

2

覆蓋onSavedInstanceState不調用它的超級。

+3

您是否可以擴展您的答案,解釋您的推理,並且在這種情況下也沒有調用super的缺陷。 – CurlyPaul 2014-05-22 10:18:18

+0

天才,我唯一的工作解決方案。 :) – Galya 2017-04-06 15:28:45

相關問題