1

I've got a fragment with a RecyclerView inside. All is working good but when I press home, navigate in other apps and then go back in my app the view gets recreated and my ArrayList (restored from onSaveInstanceState) is not displayed in my recyclerview that don't work even after updating the List.

Here some code:

-Activity

public class MainActivity extends AppCompatActivity {

    FragmentTransaction ft;
    BottomNavigationView bottomNavigationView;
    int current;
    private FirebaseAnalytics mFirebaseAnalytics;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        if(savedInstanceState==null) {
            setupFragment();
        }

//        mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);


        bottomNavigationView = (BottomNavigationView)
            findViewById(R.id.bottom_navigation);

    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

    bottomNavigationView.setOnNavigationItemSelectedListener(
            new BottomNavigationView.OnNavigationItemSelectedListener() {
                @Override
                public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                    int id = item.getItemId();
                    switch (id) {
                        case R.id.action_golden_hour:
                            changeFragment(new GoldenFragment(), "GOLDEN");
                            current=0;
                            break;
                        case R.id.action_hyperfocal:
                            changeFragment(new HyperFragment(), "HYPER");
                            current=1;
                            break;
                        case R.id.action_ir:
                            changeFragment(new IrFragment(), "IR");
                            current=2;
                            break;
                        case R.id.action_nd:
                            changeFragment(new NdFragment(), "ND");
                            current=3;
                            break;
                    }
                    return true;
                }
            });
}

@SuppressLint("CommitTransaction")
private void setupFragment(){
    ft = getSupportFragmentManager().beginTransaction();
    ft.add(R.id.main_fragment, new GoldenFragment()).commit();
    current=0;
}

@SuppressLint("CommitTransaction")
private void changeFragment(Fragment fragment, String tag){
    ft = getSupportFragmentManager().beginTransaction();
    ft.replace(R.id.main_fragment, fragment, tag).commit();
}

-Fragment

public class GoldenFragment extends Fragment implements DatePickerDialog.OnDateSetListener{

SupportPlaceAutocompleteFragment autocompleteFragment;
RecyclerView rv;
CustomAdapter adapter;
ProgressBar pb;
ArrayList<Hours> hours;
CardView cv;
TextView emptyGoldenText;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    thisContext = getContext();
    setHasOptionsMenu(true);
    ampm = !android.text.format.DateFormat.is24HourFormat(thisContext);

    hours = new ArrayList<>();
    adapter = new CustomAdapter(thisContext, hours);

    if(savedInstanceState!=null) {
        Log.d(TAG,"inState not null");
        hours.clear();
        hours = savedInstanceState.getParcelableArrayList("HoursList");
    }

    Log.d(TAG,"onCreate() called");
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    if(view == null) {
        view = inflater.inflate(R.layout.fragment_golden, container, false);
    }
    Toolbar goldenToolbar = (Toolbar) view.findViewById(R.id.toolbar_golden);
    ((AppCompatActivity) getActivity()).setSupportActionBar(goldenToolbar);

    emptyGoldenText = (TextView) view.findViewById(R.id.empty_golden_text);

    autocompleteFragment = (SupportPlaceAutocompleteFragment) getChildFragmentManager()
            .findFragmentById(R.id.place_autocomplete_fragment);

    if (autocompleteFragment == null) {
        autocompleteFragment  = (SupportPlaceAutocompleteFragment) SupportPlaceAutocompleteFragment
                .instantiate(thisContext, "com.google.android.gms.location.places.ui.SupportPlaceAutocompleteFragment");
    }
    autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
        @Override
        public void onPlaceSelected(Place place) {
            Log.i(TAG, "Place: " + place.getName());
            try {
                new GeoCoding()
                        .execute("https://maps.googleapis.com/maps/api/geocode/json?address="+place.getName()+"&key="+geoKEY);
            } catch (Exception e) {
                Toast.makeText(thisContext,"Cannot contact Google's servers, please try later.", Toast.LENGTH_SHORT).show();
                e.printStackTrace();
            }
        }

        @Override
        public void onError(Status status) {
            Log.i(TAG, "An error occurred: " + status);
        }
    });
    getChildFragmentManager().beginTransaction()
            .replace(R.id.place_autocomplete_fragment, autocompleteFragment).commit();

    //Initialize RecyclerView
    rv = (RecyclerView)view.findViewById(R.id.list_golden);
    rv.setLayoutManager(new LinearLayoutManager(thisContext));
    DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(rv.getContext(),
            getActivity().getResources().getConfiguration().orientation);
    rv.addItemDecoration(dividerItemDecoration);
    rv.setAdapter(adapter);

    cv = (CardView) view.findViewById(R.id.cv_golden);
    pb = (ProgressBar) view.findViewById(R.id.progress_bar);

    if(savedInstanceState==null) {
        Log.d(TAG,"New empty data set");

        rv.setVisibility(View.GONE);
        cv.setVisibility(View.GONE);
        pb.setVisibility(View.INVISIBLE);
    }
    else{
        Log.d(TAG,"Old data set");

        adapter.notifyDataSetChanged();
        pb.setVisibility(View.INVISIBLE);
        rv.setVisibility(View.VISIBLE);
        cv.setVisibility(View.VISIBLE);
        emptyGoldenText.setVisibility(View.INVISIBLE);
    }

    Log.d(TAG,"onCreateView() called");
    return view;
}

@Override
public void onSaveInstanceState(Bundle outState){
    super.onSaveInstanceState(outState);
    outState.putParcelableArrayList("HoursList",hours);
    Log.d(TAG,"onSaveInstanceState called");
}

SOLVED Solved by moving

adapter = new CustomAdapter(thisContext, hours);

from onCreate() to onCreateView().

rafsanahmad007
  • 23,683
  • 6
  • 47
  • 62
pgentili
  • 659
  • 5
  • 13

2 Answers2

0

In the activity, you have to save the fragment's instance in onSaveInstanceState() and restore in onCreate().

@Override
public void onCreate(Bundle savedInstanceState) {
    ...
    if (savedInstanceState != null) {     
        fragment = getSupportFragmentManager().getFragment(savedInstanceState, "KEY");
        changeFragment(fragment, "MY TAG")
    } else {
        setupFragment();
    }
    ...
}


@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    Fragment fragment = getSupportFragmentManager().findFragmentByTag("MY TAG");
    if (fragment != null) {
        getSupportFragmentManager().putFragment(outState, "KEY", fragment);
    }
}
Jean Pimentel
  • 419
  • 5
  • 10
  • This didn't work, the fragment get restored but the RecyclerView still doesn't work. I know for sure that the ArrayList isn't empty but adapter.notifydatasetchanged() does nothing. – pgentili Jan 15 '17 at 19:18
0

try this code: in onSaveInstanceState put arraylist

     @Override
public void onSaveInstanceState(Bundle outState){
    super.onSaveInstanceState(outState);
    outState.putParcelableArrayList("HoursList",hours);
    Log.d(TAG,"onSaveInstanceState called");
  }

In onActivityCreated you check the following conditions:

 @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if(savedInstanceState! = null) {
                //probably orientation change
                Log.d(TAG,"inState not null");
                hours.clear();
                hours = savedInstanceState.getParcelableArrayList("HoursList");
                //check if u get the value print log
            }
        else {
            if (hours != null) {
                //returning from backstack, data is fine, do nothing
            } else {
                //newly created, compute data
                hours = computeData();
            }
        }
    }
rafsanahmad007
  • 23,683
  • 6
  • 47
  • 62
  • Tried but this doesn't work. I think my code does the same thing but in onCreate. The problem is when I call adapter.notifydatasetchanged: the recyclerview does not get populated. – pgentili Jan 15 '17 at 19:23
  • If your getItemCount() returns 0, then notifyDataSetChanged() won't do anything. Make sure that when you initialize your adapter, you are passing a valid dataset. – rafsanahmad007 Jan 15 '17 at 19:47
  • see this:http://stackoverflow.com/questions/27714127/recyclerview-adapter-notifydatasetchanged-not-working – rafsanahmad007 Jan 15 '17 at 19:48
  • I noticed my list wasn't empty but my adapter was so i moved adapter = new CustomAdapter(thisContext, hours); from OnCreate() to OnCreateView() and it worked. – pgentili Jan 15 '17 at 21:12