旋转后片段恢复:onDetach调用两次

时间:2014-02-12 20:29:58

标签: android android-fragments

我正面临一个令我疯狂的问题。我有一个基于NavigationStudio设置的NavigationDrawer的应用程序。

我的MainActivity类有这个方法,我在其中实例化片段:

@Override
public void onNavigationDrawerItemSelected(int position) {
    Log.i(this.toString(), "onNavigationDrawerItemSelected() -> Instance new Fragment");

    // update the main content by replacing fragments
    FragmentManager fragmentManager = getSupportFragmentManager();
    Fragment fragment;
    switch (position) {
        case 0:
            fragment = new MapFragment();
            break;
        case 1:
            fragment = new SettingsFragment();
            break;
        default:
            fragment = new MapFragment();
            break;
    }

    fragmentManager.beginTransaction()
            .replace(R.id.container, fragment)
            .commit();
}

我的MapFragment覆盖了这种数据恢复方法:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    Log.i(this.toString(), "onActivityCreated savedInstanceState -> " + (savedInstanceState == null ? "NULL" : "DATA"));

    super.onActivityCreated(savedInstanceState);

    if (savedInstanceState != null) {
        // TODO: Restore markers, polylines, etc
    }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    Log.i(this.toString(), "onSaveInstanceState()");

    // Saves the data
    outState.putParcelableArray("lineas", mLineas);

    super.onSaveInstanceState(outState);
}

问题是,当我旋转设备时,系统正在调用两次。第一次,onActivityCreated接收到包OK,但第二次,它为null,导致Fragment实例没有恢复的数据。这是我的logcat:

02-12 19:19:34.866  11270-11270/com.pinard.bustracer I/MapFragment{4285f5a0 #1 id=0x7f080040}﹕ onSaveInstanceState()
02-12 19:19:34.947  11270-11270/com.pinard.bustracer I/MapFragment{4285f5a0 #1 id=0x7f080040}﹕ onDetach()
02-12 19:19:35.047  11270-11270/com.pinard.bustracer I/com.pinard.bustracer.MainActivity@42be59a0﹕ onCreate savedInstanceState -> DATA
02-12 19:19:35.047  11270-11270/com.pinard.bustracer I/MapFragment{42be7448 #1 id=0x7f080040}﹕ onAttach()
02-12 19:19:35.047  11270-11270/com.pinard.bustracer I/MapFragment{42be7448 #1 id=0x7f080040}﹕ onCreate savedInstanceState -> DATA
02-12 19:19:35.067  11270-11270/com.pinard.bustracer I/com.pinard.bustracer.MainActivity@42be59a0﹕ onNavigationDrawerItemSelected() -> Instance new Fragment
02-12 19:19:35.087  11270-11270/com.pinard.bustracer I/MapFragment{42be7448 #1 id=0x7f080040}﹕ onCreateView savedInstanceState -> DATA
02-12 19:19:35.127  11270-11270/com.pinard.bustracer I/MapFragment{42be7448 #1 id=0x7f080040}﹕ onActivityCreated savedInstanceState -> DATA
02-12 19:19:35.147  11270-11270/com.pinard.bustracer I/MapFragment{42be7448 #1 id=0x7f080040}﹕ onDetach()
02-12 19:19:35.147  11270-11270/com.pinard.bustracer I/MapFragment{42c570b8 #1 id=0x7f080040}﹕ onAttach()
02-12 19:19:35.147  11270-11270/com.pinard.bustracer I/MapFragment{42c570b8 #1 id=0x7f080040}﹕ onCreate savedInstanceState -> NULL
02-12 19:19:35.147  11270-11270/com.pinard.bustracer I/MapFragment{42c570b8 #1 id=0x7f080040}﹕ onCreateView savedInstanceState -> NULL
02-12 19:19:35.157  11270-11270/com.pinard.bustracer I/MapFragment{42c570b8 #1 id=0x7f080040}﹕ onActivityCreated savedInstanceState -> NULL
02-12 19:19:35.157  11270-11270/com.pinard.bustracer I/MapFragment{42c570b8 #1 id=0x7f080040}﹕ onStart()
02-12 19:19:35.757  11270-11270/com.pinard.bustracer I/MapFragment{42c570b8 #1 id=0x7f080040}﹕ onResume()

我在SO中已经阅读了很多内容,但无法找到解决方案。

我错过了什么?你能指点我的方向吗?

2 个答案:

答案 0 :(得分:2)

Bundle为空的原因是因为您正在创建new MapFragment。请注意,在您的日志中,第一个MapFragment位于42be7448,第二个位于42c570b8

要保持实例状态捆绑,您需要保留MapFragment实例。考虑一下这个

// Class level
private MapFragment mMapFragment;
private SettingsFragment mSettingsFragment;

Fragment fragment;
switch (position) {
    case 0:
        fragment = mMapFragment == null ? new MapFragment() : mMapFragment;
        break;
    case 1:
        fragment = mSettingsFragment == null ? new SettingsFragment() : mSettingsFragment;
        break;
    default:
        fragment = mMapFragment == null ? new MapFragment() : mMapFragment;
        break;
}

这会缓存你的碎片并允许状态继续进行。

我还认为您的Activity重新创建自身存在问题。设置回调时会调用onNavigationDrawerItemSelected,所以你看到的是。

1)你的碎片被破坏了。

2)你的活动被破坏了。

3)您的活动会被重新创建。

4)您的Fragment创建了一个新实例。 < - 这就是你需要停止的。

答案 1 :(得分:2)

    // update the main content by replacing fragments
        FragmentManager fragmentManager = getSupportFragmentManager();
    string s;
    if(position == 0)
    {
    s = MapFragment.Tag;
    }
    else
    {
    s = SettingsFragment.TAg;
    }
    Fragment fragment;
    fargment = fragmentManager.findFragmentByTag(s);

    if(null == fragment)
    {
    string tag = null;
        switch (position) {
            case 0:
                fragment = new MapFragment();
    tag = MapFragment.Tag;
                break;
            case 1:
                fragment = new SettingsFragment();
    tag = SettingsFragment.Tag;
                break;
            default:
                fragment = new MapFragment();
    tag = MapFragment.Tag;
                break;
        }
    }
        fragmentManager.beginTransaction()
                .replace(R.id.container, fragment, tag)
                .commit();

// THe code is not optimised by gives u idea what u need to do. the tags are static methods that u need to add to ur settings and map fragment