【问题标题】:How to handle rotate screen and save data in Fragment?如何处理旋转屏幕并在 Fragment 中保存数据?
【发布时间】:2016-10-25 05:42:01
【问题描述】:

我有 3 个片段(片段主页、片段 A、片段 B 和片段 C)。首次运行应用程序将显示 Fragment Home(在 Mainactivity 中设置)。从 Navigation Draw Item 可以选择每个片段。每一个被选中的item都会显示详细的Fragment。

我在处理数据和保留片段时遇到问题:

(1)。当我选择一个片段(例如片段A)时会显示片段A的页面。但是当我旋转设备时,为什么我的片段回到片段主页而不是停留在当前片段??如何处理?
(2)。在片段 B 中,我在 GridView 中显示图像。但是当我旋转设备时,为什么我的片段回到片段主页而不是停留在当前片段?如何处理它并仍然使用现有数据显示这个片段?

这是我的代码:

public class MainActivity extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener {

private static final String LOG_TAG = MainActivity.class.getSimpleName();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
        this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);

    displaySelectedItem(R.id.nav_home);
}

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    displaySelectedItem(item.getItemId());

    return true;
}

private void displaySelectedItem (int itemId) {
    Fragment fragment = null;

    switch (itemId){
        case R.id.nav_home:
            fragment = new FragmentHome();
            break;
        case R.id.nav_a:
            fragment = new FragmentA();
            break;
        case R.id.nav_b:
            fragment = new FragmentB();
            break;
        case R.id.nav_c:
            fragment = new FragmentC();
            break;
        case R.id.nav_d:
            fragment = new FragmentD();
            break;
    }

    FragmentManager fragmentManager = MainActivity.this.getSupportFragmentManager();
    List<Fragment> fragments = fragmentManager.getFragments();
    if (fragments != null) {
        for(Fragment f : fragments){
            fragmentManager.popBackStack();

        }
    }


    //replace the fragment
    if (fragment != null) {
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.content_frame, fragment, "TAG_FRAGMENT");
        fragmentTransaction.commit();
    }

    DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawerLayout.closeDrawer(GravityCompat.START);
}

片段 A:

public class FragmentA extends Fragment {
public FragmentA() {
    super();
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_a, container, false);
    return rootView;
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    getActivity().setTitle("Fragment A");
}
}

片段 B:

public class FragmentB extends Fragment {
private static final String LOG_TAG = FragmentB.class.getSimpleName();

private ImageAdapter imageAdapter;
private ArrayList<Movie> movieList;

public FragmentNowPlaying() {
    super();
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_b, container, false);
    GridView gridView = (GridView) rootView.findViewById(R.id.gridviewNowPlaying);

    imageAdapter = new ImageAdapter(getContext(), R.layout.fragment_b, movieList);
    if (savedInstanceState == null) {
        movieList = new ArrayList<Movie>();
    }else{
        movieList = (ArrayList<Movie>) savedInstanceState.get("MovieList");
    }

    gridView.setAdapter(imageAdapter);
    return rootView;
}

@Override
public void onSaveInstanceState(Bundle outState) {
    outState.putParcelableArrayList("MovieList",movieList);
    super.onSaveInstanceState(outState);
}

【问题讨论】:

标签: android android-fragments fragment android-fragmentactivity screen-orientation


【解决方案1】:

解决了这个问题。在 MainActivity 添加这个:

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt(STATE_SELECTED_POSITION, mCurrentSelectedPosition);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION, 0);
    Menu menu = navigationView.getMenu();
    menu.getItem(mCurrentSelectedPosition).setChecked(true);
}

在每个片段中添加条件以检查 savedInstanceState 是否为空。

谢谢大家

【讨论】:

    【解决方案2】:

    您需要在 Fragment A 和 B 中覆盖 onConfigurationChanged(Configuration newConfig) 方法,以告诉它们在应用配置更改时留在原处。例如:

          @Override
            public void onConfigurationChanged(Configuration newConfig) {
                    super.onConfigurationChanged(newConfig);
                    // get current fragment
                    Fragment fragment = mAdapter.getItem(currentItem);
                    if(fragment!=null){
                         fragment.onResume();
                    }
            }
    

    【讨论】:

      【解决方案3】:

      因为每次旋转屏幕都会调用 onCreate() 方法。

      解决方法

      onCreate()方法中检查savedInstanceState()是否为空

      @Override
          public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              if(null == savedInstanceState){
                   //set you initial fragment object 
              }
          else
              {
              //Load the fragment by tag
              }
        }
      

      并在所有片段中保存 onPause() 之前的实例状态

      @Override 
      protected void onSaveInstanceState(Bundle bundle1)
      { 
      super.onSaveInstanceState(bundle1); Log.i(tag,"inside onSaveInstanceState");      
      bundle1.putInt("tag",n); 
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-16
        • 2012-10-04
        • 1970-01-01
        • 2011-02-06
        相关资源
        最近更新 更多