1

I have a TripDetailFragment that contains a TripMemberFragment and a TripPhotosFragment. Inside the TripMemberFragment, I have a private instance variable Trip trip. This variable correctly gets set on the first call of a TripDetailFragment. However, on the second opening of a TripDetailFragment, this variable is null.

public class TripDetailFragment extends Fragment {

Trip trip;
Context context;
MainActivity.BottomNavAdapter adapter;
private final List<Fragment> fragments = new ArrayList<>();

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    //inflate view

    setUpFragments();

    //return inflate view

}


    private void setUpFragments(){
    fragments.add(new TripMemberFragment(trip));
    ((TripMemberFragment)fragments.get(0)).setTrip(trip);
    fragments.add(new TripPhotosFragment());
    adapter = new MainActivity.BottomNavAdapter(getChildFragmentManager(), fragments);
    vpTrip.setAdapter(adapter);
    vpTrip.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int i, float v, int i1) {

        }

        @Override
        public void onPageSelected(int i) {
            switch (i) {
                case 0:
                    tripNavigation.setSelectedItemId(R.id.action_members);
                    break;
                case 1:
                    tripNavigation.setSelectedItemId(R.id.action_photos);
                    break;
            }
        }

        @Override
        public void onPageScrollStateChanged(int i) {

        }

    });
    tripNavigation.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch(item.getItemId()){
                case R.id.action_members:
                    vpTrip.setCurrentItem(0);
                    return true;
                case R.id.action_photos:
                    vpTrip.setCurrentItem(1);
                    return true;
                default:
                    return false;
            }
        }
    });
}

}

public class TripMemberFragment extends Fragment {
    private Trip trip;

    public TripMemberFragment(Trip trp) {
    trip = trp;
    }

    public  TripMemberFragment(){}

        @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

        // Inflate the layout for this fragment

        members = new ArrayList<>();
        memberAdapter = new TripMemberAdapter(members, callbackMember);

        rvMembers.setLayoutManager(new LinearLayoutManager(context));
        rvMembers.setAdapter(memberAdapter);

        loadMembers();

        //return inflated view

    }

   public void loadMembers(){

       try{
           ParseRelation relation = trip.getRelation("user");
           ParseQuery query = relation.getQuery();

           query.findInBackground(new FindCallback<ParseUser>() {
           @Override
           public void done(List<ParseUser> objects, ParseException e) {
                Log.d("relation", objects.toString());
                members.clear();
                members.addAll(objects);
                memberAdapter.notifyDataSetChanged();
              }
           });
      }catch (Exception e){
        e.printStackTrace();
      }

   }
}

There no logged errors or exceptions when run but the trip variable in TripDetailFragment is null when calling loadMembers() on the second run, but it seems to be correctly getting set when the constructor for the fragment is called. I think there may be an issue with putting the setUpFragments() in the onCreateView() but don't know where else it could go.

Kathy
  • 41
  • 1
  • 1
  • 6

1 Answers1

0

First of all, you should use static factory method for creating a new instance of Fragment like this:

public static TripMemberFragment newInstance(Trip trip) {
    TripMemberFragment fragment = new TripMemberFragment();
    Bundle extras = new Bundle();
    extras.putParcelable(“EXTRA_TRIP, trip);  // or use here putSerializable method if you working with Serializable objects
    fragment.setArguments(extras);
    return fragment;
}

And you should now everytime you need an instance of Fragment use this newInstance method. So you need to remove all constructors from your fragments to prevent creating an instance of fragments with constructors.

Trip object can be obtained from Fragment arguments like this:

getArguments().getParcelable(“EXTRA_TRIP”) // or use here getSerializable method if you working with Serializable objects

In setUpFragments method inside of a TripDetailFragment you can replace those lines:

fragments.add(new TripMemberFragment(trip));
((TripMemberFragment)fragments.get(0)).setTrip(trip);
fragments.add(new TripPhotosFragment());

with:

fragments.add(TripMemberFragment.newInstance(trip));
fragments.add(pTripPhotosFragment.newInstance());

I have a feeling that passed object is getting lost somehow. If you pass an object with Arguments, then the object should persist on fragment instance inside getArguments() method.

BVantur
  • 1,182
  • 16
  • 11
  • Thanks! This has fixed the error of the trip persisting. However, the same trip now persists even when a different trip should be passed. I have tried using a trip setter method in TripMemberFragment and then call it before the fragment is displayed, but it still seems to keep the trip argument set on the first call. – Kathy Jul 20 '18 at 22:51
  • Can you please post the part of code how do you change the Trip object on TripDetailFragment instance. Also, TripDetailFragment should also use **static method factory** for creating an instance. – BVantur Jul 21 '18 at 02:35
  • I use 'public void setTrip(Trip trip) { this.getArguments().putParcelable(TRIP_ARG, trip); }' and call that in TripDetailFragment. TripDetailFragment is used in a viewpager in the main activity before a Trip is set so I initialize it with the default empty constructor. I have also tried setting the trip by changing 'setTrip(Trip trip)' to set trip by calling 'this.trip = trip'. @BVantur – Kathy Jul 23 '18 at 17:29
  • Can you somehow provide me with the whole source code of the project? – BVantur Jul 23 '18 at 22:04