在运行时构建的片段上始终为 null savedInstanceState(导航视图)

always null savedInstanceState on Fragment built at runtime (navigation view)

我正在尝试使用一个 Activity 和与导航项一样多的 Fragment 来构建 NavigationView: 点击的第一项 --> 第一个片段加载随机远程图像; second/third 项目点击 --> 其他片段被加载。 我的目标是,在切换回第一项时,显示已下载的图片而不是获取新图片。

activity_main.xml

<android.support.v4.widget.DrawerLayout
(.....)
android:id="@+id/drawer_layout">

<!-- This LinearLayout represents the contents of the screen  -->
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!-- The ActionBar displayed at the top -->
    <include
        layout="@layout/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <!-- The main content view where fragments are loaded -->
    <FrameLayout
        (......)
        android:id="@+id/flContent"/>
</LinearLayout>

<!-- The navigation drawer that comes from the left -->
<android.support.design.widget.NavigationView
    (.......)
    android:id="@+id/nvView" />

主要Activity

public class MainActivity extends AppCompatActivity {

Fragment homeFragment;

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //......
    setupDrawerContent(nvDrawer);
    if (findViewById(R.id.flContent) != null && savedInstanceState == null) {
       homeFragment = new HomeFragment();
       getSupportFragmentManager().beginTransaction().add(R.id.flContent, homeFragment, "homeFragment").commit();
    }
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    getSupportFragmentManager().putFragment(outState, "homeFragment", homeFragment);
}

private  void setupDrawerContent(NavigationView navigationView) {
    navigationView.setNavigationItemSelectedListener(
            new NavigationView.OnNavigationItemSelectedListener() {
                @Override
                public boolean onNavigationItemSelected(MenuItem menuItem) {
                    selectDrawerItem(menuItem);
                    return true;
                }
            }
    );
}

public void selectDrawerItem(MenuItem menuItem) {
    // Create a new fragment and specify the item to show based on
    // position
    Fragment fragment = null;

    Class fragmentClass = null;
    switch(menuItem.getItemId()) {
        case R.id.nav_first_fragment:
            fragmentClass = HomeFragment.class;
            break;
        case R.id.nav_second_fragment:
            fragmentClass = SecondFragment.class;
            break;
        default:
            fragmentClass = HomeFragment.class;
    }
    try {
        fragment = (Fragment) fragmentClass.newInstance();
    } catch (Exception e) {
        e.printStackTrace();
    }

    // Insert the fragment by replacing any existing fragment
    FragmentManager fragmentManager = getSupportFragmentManager();
    fragmentManager.beginTransaction().replace(R.id.flContent, fragment).commit();

    // Highlight the selected item, update the title, and close the drawer
    menuItem.setChecked(true);
    setTitle(menuItem.getTitle());
    mDrawer.closeDrawers();
   }
}

主页片段

    public class HomeFragment extends Fragment {


    private static final String TAG = "HomeFragment";

    public HomeFragment() {
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        // ......
        View fragmentView = inflater.inflate(R.layout.home_fragment, container, false);
        if (savedInstanceState == null) {
            // FETCH RANDOM IMAGE
        }else {
            // RESTORE IT (but always null)
        }
        return fragmentView;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putSerializable(/*SOME DATA*/);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (savedInstanceState != null) {
            // ALWAYS NULL
        }
    }
 }

我找到了 this 答案,但我不知道该怎么做,因为我只是参考了 FrameLayout。

跟踪生命周期方法我注意到 MainActivity 始终处于活动状态,因此它从不调用 onSaveInstanceState,而且我不知道如何在 HomeFragment 中使用 Bundle 来恢复 onCreateView 中的 savedInstanceState。 你有什么提示要分享吗? 非常感谢

当您用另一个片段替换一个片段时,前一个片段(被替换)将被破坏,并且它在其非静态成员变量中的任何数据都将丢失。

如果要为片段保留图像,可以使用位图缓存来存储图像,但这只有在为片段加载相同图像时才有效。如果您正在加载随机图像并希望在下次实例化相同片段时加载相同图像(因此您希望 Home 片段始终加载它在第一次实例化时加载的相同图像),那么您需要坚持数据。有几种方法可以做到这一点,你可以在你的 Home 片段中使用一个静态变量来保存图像的 URL,你可以将它存储在 SharedPreferences 中,你可以将它传递给 Activity 所以activity 然后会在再次创建时将其传回 Home 片段,依此类推。选择最适合您需求的解决方案。