【问题标题】:Fragment onCreateView and onActivityCreated not being called on rotation片段 onCreateView 和 onActivityCreated 没有在旋转时被调用
【发布时间】:2014-04-30 15:14:06
【问题描述】:

我正在处理片段并将新片段推送到后台堆栈,但是当我将设备旋转两次时,片段生命周期中的片段onCreateViewonActivityCreated 等方法永远不会被调用,留下空白屏幕。这只发生在片段被添加到后台堆栈或返回到后台堆栈中的第一个片段时。

这是我的activity的片段处理方法:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Injection
    MormonChannel.injectActivity(this);

    setDrawerIndicatorEnabled(true);

    // Do not set currentNavigationItem here.
    NavigationItemSelectedEvent.NavigationItem navItem = null;
    Intent intent = getIntent();
    if (intent != null) {
        navItem = (NavigationItemSelectedEvent.NavigationItem)
        intent.getSerializableExtra(EXTRA_NAV_ITEM);
    }

    if (savedInstanceState == null) {
        FragmentManager fm = getSupportFragmentManager();
        fm.beginTransaction().replace(R.id.container, new FeatureListFragment()).commit();
        if (navItem != null) {
            onNavigationItemSelected(new NavigationItemSelectedEvent(navItem));
        } else {
            currentNavigationItem = NavigationItemSelectedEvent.NavigationItem.FEATURES;
        }
    }

}

@Subscribe
public void onNavigationItemSelected(NavigationItemSelectedEvent event) {

    if (currentNavigationItem == event.getNavigationItem()) {
        return;
    }
    FragmentManager fragmentManager = getSupportFragmentManager();
    fragmentManager.popBackStack();
    NavigationItemSelectedEvent.NavigationItem navigationItem = event.getNavigationItem();
    String name = navigationItem.getName();
    switch (navigationItem) {
        default:
        case FEATURES:
            // Nothing needs to be done it is already there.
            break;
        case AUDIO:
            fragmentManager.beginTransaction().replace(R.id.container,
                    CollectionListFragment.newInstance(prefs.getLanguageId(), prefs.getAudioCollectionId()))
                    .addToBackStack
                            (name).commit();
            break;
        case VIDEO:
            fragmentManager.beginTransaction().replace(R.id.container,
                    CollectionListFragment.newInstance(prefs.getLanguageId(), prefs.getVideoCollectionId()))
                    .addToBackStack(name).commit();
            break;
        case RADIO:
            fragmentManager.beginTransaction().replace(R.id.container,
                    CollectionListFragment.newInstance(prefs.getLanguageId(), prefs.getRadioCollectionId()))
                    .addToBackStack(name).commit();
            break;
        case HISTORY:
            fragmentManager.beginTransaction().replace(R.id.container, new HistoryFragment()).addToBackStack(name).commit();
            break;
        case DOWNLOADS:
            fragmentManager.beginTransaction().replace(R.id.container, new DownloadsFragment()).addToBackStack(name).commit();
            break;
        case PLAYLISTS:
            fragmentManager.beginTransaction().replace(R.id.container, new PlaylistFragment()).addToBackStack(name).commit();
            break;
    }
    currentNavigationItem = navigationItem;
}

这是我的 CollectionListFragment 代码:

 @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MormonChannel.injectFragment(this);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.collection_list_fragment, container, false);
    ButterKnife.inject(this, v);
    return v;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    listView.setDividerHeight(0);
    listView.setFastScrollEnabled(true);


    Bundle args = getArguments();
    if (args != null) {
        languageId = args.getLong(ARG_LANGUAGE_ID, -1L);
        collectionId = args.getLong(ARG_COLLECTION_ID, -1L);
        if (args.containsKey(ARG_SORT)) {
            sort = (Sort) args.getSerializable(ARG_SORT);
        }
    }

    if (collectionId == -1L || languageId == -1L) {
        // TODO Implement Empty Collection Text
    } else {
        collection = collectionManager.findByCollectionId(languageId, collectionId);
        getLoaderManager().initLoader(LOADER_ID, null, this);
    }

    titleEvent = new TitleChangeEvent(collection != null ? collection.getTitle() : getString(R.string.app_name));
    bus.post(titleEvent);
}

活动清单:

<activity
    android:name=".activity.MainActivity"
    android:launchMode="singleTask">
    <meta-data
        android:name="android.app.default_searchable"
        android:value=".activity.SearchActivity"/>
</activity>

【问题讨论】:

  • 这个讲座可能会对你有所帮助:stackoverflow.com/questions/8474104/… 它有一些很好的解释性答案
  • 我正在通过我的 Activity 的 onCreate 方法考虑到这一点。
  • Manifest 中没有 Activity 的“configChanges”元素是吗?这将阻止 Activity 在旋转时重新创建。
  • 第一次轮换无效,但第二次,第三次,...不。

标签: android android-fragments fragmenttransaction


【解决方案1】:

在您的 CollectionListFragment 代码中,在 onCreate() 方法中添加对 setRetainInstance() 方法的调用,并将 true 作为其参数:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);
    MormonChannel.injectFragment(this);

}

使用 setRetainInstance(true) 可确保当配置更改发生时,活动将被终止,但 android 不会破坏它所托管的片段。

相反,android 会保存片段状态并将片段从活动中分离出来。它也不会破坏片段,因此稍后在创建托管活动时不会创建它。因此片段不会收到对其 onDestroy() 和 onCreate() 方法的调用。

【讨论】:

猜你喜欢
  • 2012-06-14
  • 2011-12-23
  • 1970-01-01
  • 1970-01-01
  • 2014-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多