How to handle rotate screen and save data in Fragment?

拈花ヽ惹草 提交于 2021-02-08 08:17:24

问题


I have 3 Fragment (Fragment Home, Fragment A, Fragment B and Fragment C). First time app run will display Fragment Home (Set in Mainactivity). From Navigation Draw Item can choose every fragment. Every selected item will display detail Fragment.

I have problems to handle data and retain fragment :

(1). When I select a fragment (for example Fragment A) will show the page of Fragment A. But when I rotate the device, why my fragment back to Fragment Home and not stay at current Fragment ??How to handle it ?

(2). In Fragment B, I show image in GridView. But when I rotate the device, why my fragment back to Fragment Home and not stay at current Fragment ??How to handle it and still display this fragment with existing Data?

This is my code :

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);
}

Fragment 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");
}
}

Fragment 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);
}

回答1:


Solved this issue. In MainActivity add this :

@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);
}

In every fragment add condition to check savedInstanceState null or not.

Thanks everybody




回答2:


You need to override onConfigurationChanged(Configuration newConfig) method in your Fragments A and B to tell them to stay there when the app configuration change. For example:

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



回答3:


Because every time you rotate the screen the onCreate() method is called.

work around

in onCreate() method check whether the savedInstanceState() is null or not

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

and to save the instance state just before onPause() in all fragments

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

}


来源:https://stackoverflow.com/questions/40232149/how-to-handle-rotate-screen-and-save-data-in-fragment

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!