Mam ten dziwny problem, w którym mój fragment listy jest tworzony dwa razy, jeden raz, gdy super.oncreate jest wywoływany w macierzystej aktywności i raz, gdy setContentView jest wywoływana na tej samej nadrzędnej aktywności. Jest to prosta aplikacja, w której używam innego układu do orientacji pionowej i poziomej.Fragment android utworzony dwa razy na zmianę orientacji
Oto Główna działalność:
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();
}
}
}
tutaj jest news_articles w folderze layout-land:
<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" />
tutaj jest news_articles w folderze układu (dla orientacji pionowej)
<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" />
tutaj jest ów headlinesfragment zostały utworzone dwa
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();
}
}
jest tu 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();
}
}
Problem szczegółowo to:
1) rozpoczyna się na stosowanie w orientacja portretowa 2) wywoływana jest funkcja setContentView, a element news_articles jest załadowany, ale jest to element zawierający fragment ment_container. 3) headlinesfragment jest tworzony // dotąd normalne zachowanie orientację 4) do zmiany krajobrazu 5) główną działalność jest zniszczona -> headlinefragment jest zniszczona 6) super.oncreate na główną działalność nazywa 7) Headlinefragment jest tworzony 8) setcontentview na główną działalność nazywa 9) inny headlinefragment jest tworzony // problem
umieściłem dzienniki jak widać w powyższym kodzie i tu jest wyjście kiedy uruchomić aplikację w trybie pionowym i zmieni się krajobraz.
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}
Mam nadzieję, że było jasne, z mojego kodu i dzienników, wydaje mi super.oncreate i setcontentview zarówno tworzenia się headlinesfragment każda; przynajmniej myślę.
Moje pytanie brzmi: dlaczego powstają 2 egzemplarze nagłówków i jak mogę uniknąć takiej sytuacji.
wielkie dzięki za wszelką pomoc dotyczącą tego
Dziękuję za odpowiedź, ale problem pojawia się, gdy aplikacja zmienia orientację poziomą, tak więc kod, który podałeś, nie jest wykonywany. Również w odniesieniu do kodu, który podałeś, kiedy aplikacja uruchamia się najpierw w trybie pionowym, zapisana wartośćInstanceState ma wartość null, a blok else jest wykonywany, więc w jaki sposób możemy znaleźć nagłówek HeadlinesFragment po tagu, jeśli nigdy nie stworzyliśmy go w pierwszej kolejności? –
Myślę, że warunek instrukcji if jest tutaj wstecz. Jeśli istnieje zapisany stan wystąpienia, powinieneś znaleźć istniejący fragment. Jeśli zapisany stan wystąpienia ma wartość NULL, powinieneś utworzyć nowy fragment. – Razz
@Razz jest poprawny. UWAGA: jeśli savedInstanceState IS jest null, tworzysz nowy fragment, w przeciwnym razie fragment już istnieje! Więc, zmień wewnętrzną instrukcję if na if (savedInstanceState == null) –