对方向变化所造成的Andr​​oid的两倍片段 [英] android fragment created twice on orientation change

查看:100
本文介绍了对方向变化所造成的Andr​​oid的两倍片段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有在我的名单片段创建两次,一次当super.oncreate被称为父活动,一旦当的setContentView被称为在同一个父活动这个奇怪的问题。这是一个简单的应用程序,我使用的纵向和横向不同的布局。

i am having this weird problem where my list fragment is created twice, once when the super.oncreate is called on the parent activity and once when the setContentView is called on the same parent activity. It is a simple application where i use different layout for portrait and landscape orientation.

下面是主要的活动:

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:

here is the news_articles in layout-land folder:

<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(对于纵向)

here is the news_articles in layout folder (for the portrait orientation)

<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这就是被创建两次

here is the headlinesfragment thats been created twice

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

here is the 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加载但其一个具有fragment_container。
3)创建headlinesfragment //到目前为止正常行为
4)改变方向为横向
5)mainActivity被破坏 - > headlinefragment被破坏
6)mainactivity super.oncreate称为
7)被创建Headlinefragment
8)mainactivity的setContentView称为
创建9)其他headlinefragment //问题

1) start the application in portrait orientation 2) the setContentView is called and news_articles is loaded but its the one with the fragment_container. 3) headlinesfragment is created // so far normal behaviour 4) change orientation to landscape 5) mainActivity is destroyed -> headlinefragment is destroyed 6) super.oncreate on mainactivity is called 7) Headlinefragment is created 8) setcontentview on mainactivity is called 9) another headlinefragment is created //problem

我已经放在日志,可以在code以上可以看出,这里是输出的时候我开始在纵向模式的应用程序,我更改为横向。

i have placed the logs as can be seen in the code above and here is the output when i start the app in portrait mode and i change to landscape.

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

我希望我已经与我的code和原木清晰的,在我看来super.oncreate和双方的setContentView创建每次一个headlinesfragment;至少我认为。

I hope i have been clear with my code and logs, it seems to me super.oncreate and setcontentview both create a a headlinesfragment each; at least i think.

我的问题是,为什么会创建2 headlinesfragment实例,我怎么能避免这种情况。

my question is why 2 headlinesfragment instances are created and how i can avoid such a situation.

非常感谢您的帮助对本

推荐答案

的onCreate 您的活动,您可以检查您的状态 savedInstanceState 捆绑。如果不为空,则意味着发生了配置改变(在你的情况下,屏幕方向变化),而且你不需要重新创建片段

In the onCreate of your Activity, you can check the state of your savedInstanceState bundle. If it isn't null, it means a configuration change occurred (in your case, an screen orientation change) and that you don't need to recreate your Fragment.

这是你在做另外一个错误是,你正试图找回你的片段 findFragmentById 。相反,传递片段的id,你给它贴在片段,这是不同的视图的ID(这就是为什么我猜这总是返回null的原因)。

Another mistake that you were doing was that you were trying to retrieve your Fragment with the findFragmentById. Instead of passing the Fragment id, you're giving it the id of the View attached to the Fragment, which is different (and that's the reason why I'm guessing this was always returning null).

有一个正确的执行会更喜欢这个(这是你的活动

A correct implementation would be more like this (this is your 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);
        } 
   }

这篇关于对方向变化所造成的Andr​​oid的两倍片段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆