1

Im having an issue that only appears after several hours of inactivity, I researched it ive tried various ways of fixing it to no avail. The issue is after my app has been dormant for several hours the references for my fragments are null, however; they still exist in the frag manager. I use the references to pull the tag, or id by findfragmentby...() so I can call specific methods within them for updating themselves and what not. The fragments are dynamic and have a UI. I have several activities and a service that are called on by the main activity. I can close the app and resume, call activities, pull info from the service, close, use the back button, all without an issue. To give you an idea of how the app is structured...

public class appClass extends Application {
public Fragment fragmentA;
public Fragment fragmentB;
public Fragment fragmentC;
@Override
public void onCreate() {
    super.onCreate();
    new fragmentTemplate();
    fragemntA = fragmentTemplate.newInstance(getDbName(), usefuldata, "A List");
    new fragmentTemplate();
    fragemntB = fragmentTemplate.newInstance(getDbName(), usefuldata, "B list");
    new fragmentTemplate();
    fragemntC = fragmentTemplate.newInstance(getDbName(), usefuldata, "C list");

      }
}

Moving on to activity where fragments are used in a viewager...

    public class mainActivity extends AppCompatActivity implements ...listeners{
    appClass myAppClass;
    FragmentManager FragMgr;
    ViewPager viewPager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        myAppClass = (appClass) getApplication();
        setTheme(myAppClass.getAppTheme());
        setContentView(R.layout.activity_my_layout);
        //toolbar actionbar stuff
        FragMgr = getSupportFragmentManager();

        viewPager = (ViewPager) findViewById(R.id.viewpager);
        viewPager.setAdapter(new ViewPagerAdapter(FragMgr));

        //tab setup

    }
    //inner class pager adapter is here 
}

This is my pager adapter

class ViewPagerAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener{
        Fragment fragment;


        public ViewPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            switch (position) {
                case 0:
                    if (myAppClass.fragmentA != null) {
                        fragment = myAppClass.fragemntA ;
                    } 
                    break;
                case 1:
                    if (myAppClass.fragmentB != null) {
                        fragment = myAppClass.fragmentB ;
                    } 
                    break;
                case 2:
                    if (myAppClass.fragmentC != null) {
                        fragment = myAppClass.fragmentC ;
                    } 
                    break;
            }

            return fragment;
       }
       @Override
       public int getCount() {
        return 3;
      }
}

I have a FAB and its listener looks like this

@Override
    public void onClick(View v) {
        Fraggment fragment;
        int i = viewPager.getCurrentItem();
        if (v.getId() == floatingActionButton.getId()) {

            switch (i) {
                case 0:
                    fragment= (Fragment) FragMgr.findFragmentByTag(myAppClass.fragmentA.getTag());
                    fragment.addItem(fragment.getSomeString());
                    break;
                case 1:
                    fragment= (Fragment) FragMgr.findFragmentByTag(myAppClass.fragmentB.getTag());
                    fragment.addItem(fragment.getSomeString());
                    break;
                case 2:
                    fragment= (Fragment) FragMgr.findFragmentByTag(myAppClass.fragmentC.getTag());
                    fragment.addItem(fragment.getSomeString());
                    break;
            }

        }
    }

code for a fragment

public class fragmentTemplate extends Fragment implements RecyclerAdapter.aListener {

    private appClass myAppclassReference;
    private RecyclerView recyclerView;
    private View view;
    private FragmentTitle;

    public static fragmentTemplate newInstance(String a, String b, String c) {

        Bundle args = new Bundle();
        args.putString(KEY_A, a);
        args.putString(KEY_B, b);
        args.putString(KEY_C, c);
        fragmentTemplate fragment = new fragmentTemplate();
        fragment.setArguments(args);
        return fragment;
    }

    public String getFragmentTitle() {
        return fragmentTitle;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, final Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.list, container, false);
        myAppclassReference= ((appClass) getActivity().getApplication());
        recyclerView = (RecyclerView) view.findViewById(R.id.listView);
        //get list is a local function that loads a list from a db source
        RecyclerAdapter recycler = new RecyclerAdapter(getActivity(), getList());
        recycler.setListener(this);
        recyclerView.setAdapter(recycler);  
        recyclerView.setLayoutManager(newLearLayoutManager(getActivity()));
        recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new ClickListener() {}};
        return view;
        }
}

When things go wonky the app does not crash right away, the tabs still scroll, the viewpager still scrolls, but it is empty, its not until I hit the FAB do I get a nullpointerexception, trying to invoke a method on a nullpointer reference within the onClick Listener does it actually crash.

Shaotim
  • 41
  • 3

1 Answers1

0

This is happening because you are messing up with the way that the Android Framework handles Fragments for you. When the ViewPagerAdapter gets Fragments from you in getItem(int), it's using the FragmentManager that you gave it to attach the Fragments. Once the Activity is killed because of low memory, the FragmentManager will automatically create new instances of your Fragments. At this point there are two copies of the fragments, the ones the FragmentManager created and the ones you recreated in your appClass.

You should never keep references to your Fragments. The FragmentManager is free to destroy them and create new ones. If you need to communicate between the Activity and the Fragments in the ViewPager, you can either make the Fragment ask its Activity for commands, use an Event Bus, or explore the sketchy solutions here.

Community
  • 1
  • 1
sorianiv
  • 4,845
  • 1
  • 23
  • 27