У меня возникла эта странная проблема, когда фрагмент списка создается дважды, один раз, когда super.oncreate вызывается в родительской активности и один раз, когда setContentView вызывается с тем же родительским действием. Это простое приложение, в котором я использую разные макеты для портретной и альбомной ориентации.андроидный фрагмент, созданный дважды при изменении ориентации
Вот основной вид деятельности:
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, а его - с фрагментом ment_container. 3) headlinesfragment создается // до сих пор нормальное поведение ориентации 4) изменения в ландшафт 5) mainActivity разрушается -> headlinefragment разрушается 6) super.oncreate на mainactivity называется 7) Headlinefragment создается 8) setcontentview на mainactivity называется 9) создается другой headlinefragment // проблема
Я разместил журналы, как показано в приведенном выше коде, и вот результат, когда я запускаю приложение в портретном режиме, и я перехожу к пейзажу.
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 экземпляра headlinesфрагментов создаются и как я могу избежать такой ситуации.
большое спасибо за любую помощь в отношении этого
Спасибо за ваш ответ, однако проблема в том, что приложение обращается к альбомной ориентации, поэтому код, который вы указали, не выполнен в любом случае. Также в отношении кода, который вы указали, когда приложение запускается в портретном режиме, файл savedInstanceState равен null, а блок else выполняется так, как мы можем найти тег HeadlinesFragment по тегам, если мы никогда не создадим его в первую очередь? –
Я думаю, что условие if if здесь назад. Если есть состояние сохраненного экземпляра, вы должны найти существующий фрагмент. Если сохраненное состояние экземпляра равно NULL, вы должны создать новый фрагмент. – Razz
@Razz правильный. ПРИМЕЧАНИЕ: если savedInstanceState IS null, то вы создаете новый фрагмент, иначе фрагмент уже существует! Итак, просто измените внутренний оператор if на if (savedInstanceState == null) –