Updating a fragment in response to Android Navigation Drawer interaction

爷,独闯天下 提交于 2019-12-05 04:56:43

Keeping a reference to a Fragment might leave you out of sync with a reference to an old Fragment that is Detached in cases where the Fragment Manager recreates the Fragment for you.

The solution is to find the fragment currently in frag_frame, in pseudo code:

Fragment fragment = fm.findFragmentById(R.id.frag_frame);
if(fragment instanceof BrowseFragment) {
   // do your stuff
}

Just replace onclick listener code with this one in mainactivity.

Error is occuring due to NullPointerException,

cause: Null pointer passing in replace 2nd column.

Solution : initiate fragment class (new fragment())

case R.id.home:
    hfragment = new homefragment();
    FragmentTransaction hfragmentTransaction= getSupportFragmentManager().beginTransaction();
    hfragmentTransaction.replace(R.id.frame, hfragment);
    hfragmentTransaction.commit();
    //do ur task here or in fragment class
    return true;


case R.id.notification:
    return true;

default:
    Toast.makeText(getApplicationContext(),"Somethings Wrong",Toast.LENGTH_SHORT).show();
    return true;

I notice you're basically caching fragments due to code of:

public class MainActivity extends Activity implements MainStateListener {
   private FragmentManager fm = getFragmentManager();
   private BrowseFragment browseFragment = BrowseFragment.newInstance();

But implementing this may be tricky. Either you create code/class that manages these fragments like using Array of fragments, or use class like FragmentPagerAdapter.

If I may suggest, don't cache fragments since you have to understand its lifecycle, caching is a good idea only if the fragment's layout is complicated. Simply just create a new instance of it in your code public void onItemClick() like at Google's suggestion @ Creating a Navigation Drawer, in case you did not read it. Code snippet in the webpage:

private class DrawerItemClickListener implements ListView.OnItemClickListener {
    @Override
    public void onItemClick(AdapterView parent, View view, int position, long id) {
        selectItem(position);
    }
}

private void selectItem(int position) {
    // Create a new fragment and specify the planet to show based on position
    Fragment fragment = new PlanetFragment();
    Bundle args = new Bundle();
    args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);
    fragment.setArguments(args);

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

Note: A new instance of fragment is done with new PlanetFragment().

What I think may be happening is that your activity's browseFragment may be different that the BrowseFragment that is being shown by the fragment manager (which seems to work fine as you said if you click a button in that fragment).

On rotation, the activity will create a NEW BrowseFragment instance for your browseFragment variable (which is not attached to the activity) - private BrowseFragment browseFragment = BrowseFragment.newInstance() runs each time the activity is created, but the fragment manager will reuse the EXISTING BrowseFragment instance which your variable does NOT point to. The reused BrowseFragment will get attached and run that code to update the mainStateListener, the unused new browseFragment won't be attached to the activity unless you run through a fragmentTransaction that adds it - so the mainStateListener in it will be null (uninitialized).

Instead of creating the fragment and storing it in a variable and then trying to access that variable after a rotation, you would be better off using a fragment tag and getting the fragment based on the tag from the fragment manager.

i.e.

private static final String BROWSE_TAG = "browseFrag";

ft.replace(R.id.frag_frame, browseFragment, BROWSE_TAG);

navigationDrawer.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        Fragment browseFragment = fm.findFragmentByTag(BROWSE_TAG);
        if (browseFragment != null) {
            browseFragment.doSomethingOnBrowserFragment();
        }
   }
});
Mina Samy

I believe you need to set your listener each time the activity is created. Also using a weak reference is helpful.

please check my answer here: IllegalStateException: Can not perform this action after onSaveInstanceState with ViewPager

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