KeenLearner KeenLearner - 3 months ago 28
Android Question

How to save and restore custom arrayadapter data when switching fragments

I've tried different answers on this forum that are related to my problem but none seem to work for me.

ArrayAdapter Class

public class UserAdapter extends ArrayAdapter<User> {
public UserAdapter(Context context, ArrayList<User> users) {
super(context, 0, users);
}

private static class ViewHolder {
TextView water;
TextView amount;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
User user = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder viewHolder; // view lookup cache stored in tag
if (convertView == null) {
// If there's no view to re-use, inflate a brand new view for row
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.card, parent, false);
viewHolder.water = (TextView) convertView.findViewById(R.id.WaterConsumed);
viewHolder.amount = (TextView) convertView.findViewById(R.id.WaterAmount);
// Cache the viewHolder object inside the fresh view
convertView.setTag(viewHolder);
} else {
// View is being recycled, retrieve the viewHolder object from tag
viewHolder = (ViewHolder) convertView.getTag();
}
// Populate the data into the template view using the data object
viewHolder.water.setText(user.waterconsum);
viewHolder.amount.setText(user.amount);
// Return the completed view to render on screen
return convertView;
}


User Class

public class User implements Serializable{
String waterconsum;
String amount;

public User(String waterconsum, String amount) {
this.waterconsum = waterconsum;
this.amount = amount;
}


One of the fragment class that shows the data

public class WaterFragment extends Fragment {

ArrayList<User> arrayOfUsers = new ArrayList<User>();
UserAdapter adapter;

View view;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setRetainInstance(true);
if (savedInstanceState != null) {
arrayOfUsers = (ArrayList<User>) savedInstanceState.getSerializable("List");
}
return view = inflater.inflate(R.layout.water, container, false);
}

public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setRetainInstance(true);
Button button = (Button) view.findViewById(R.id.additem);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
showInputDialog();
}
});

adapter = new UserAdapter(getActivity(), arrayOfUsers);
ListView listView = (ListView) view.findViewById(R.id.listofitems);
if (listView.getAdapter() != null) {
listView.onRestoreInstanceState(savedInstanceState);
} else {
listView.setAdapter(adapter);
}


}

protected void showInputDialog() {
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
final View promptView = layoutInflater.inflate(R.layout.input_dialog, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
alertDialogBuilder.setView(promptView);
final EditText editText = (EditText) promptView.findViewById(R.id.edittext);

alertDialogBuilder.setCancelable(false)
.setPositiveButton("Submit", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String text = editText.getText().toString();
addItems(text);
}
})
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});

AlertDialog alert = alertDialogBuilder.create();
alert.show();
}

public void addItems(String text) {
arrayOfUsers.add(new User("Water Consumed Today", text));
}

@Override
public void onSaveInstanceState(Bundle state) {
state.putSerializable("List", arrayOfUsers);
super.onSaveInstanceState(state);
}


Whenever i switch between different fragments, the array data is always reset. So im not sure on how to go about solving this, i've tried various solutions that involved saving the fragment state and the array data but none seem to work so far.

EDIT: Fragment Handler class

@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calendar);

bottomBar = BottomBar.attach(this, savedInstanceState);
bottomBar.setItemsFromMenu(R.menu.three_buttons_menu, new OnMenuTabSelectedListener() {
@Override
public void onMenuItemSelected(@IdRes int menuItemId) {
if (menuItemId == R.id.Calendar) {
CalendarFragment f = new CalendarFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frame, f).commit();
} else if (menuItemId == R.id.Water) {
WaterFragment wf = new WaterFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frame,wf).commit();
} else if (menuItemId == R.id.Advice) {
AdviceFragment af = new AdviceFragment();
getSupportFragmentManager().beginTransaction().add(R.id.frame, af).commit();
} else if (menuItemId == R.id.Diary) {
AdviceFragment af = new AdviceFragment();
getSupportFragmentManager().beginTransaction().add(R.id.frame, af).commit();
} else if (menuItemId == R.id.Help) {
AdviceFragment af = new AdviceFragment();
getSupportFragmentManager().beginTransaction().add(R.id.frame, af).commit();
}
getFragmentManager().executePendingTransactions();

}
});

Answer

create your adaptor only once in onCreate of your fragment.

and in your onViewCreated set this adaptor to listview.

private UserAdapter adapter;
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(adapter==null)
            adapter = new UserAdapter(getActivity(), arrayOfUsers);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle    savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        ListView listView = (ListView) view.findViewById(R.id.listofitems);
        listView.setAdapter(adapter);
    }

and whenever data changes add new items in adapter and call notifyDataSetChanged.

UPDATE: From your Fragment Handler class, you are creating new instance everytime you are replacing fragment like

CalendarFragment f = new CalendarFragment();

I'll suggest you to do like this..

private CalendarFragment calenderFragment;
    private WaterFragment waterFragment;
    private AdviceFragment adviceFragment;


    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_calendar);

        calenderFragment = new CalendarFragment();
        waterFragment = new WaterFragment();
        adviceFragment = new AdviceFragment();

        bottomBar = BottomBar.attach(this, savedInstanceState);
        bottomBar.setItemsFromMenu(R.menu.three_buttons_menu, new OnMenuTabSelectedListener() {
            @Override
            public void onMenuItemSelected(@IdRes int menuItemId) {
                if (menuItemId == R.id.Calendar) {
                    if(calenderFragment==null)
                        calenderFragment = new CalendarFragment();
                    getSupportFragmentManager().beginTransaction().replace(R.id.frame, calenderFragment)
                            .commit();
                } else if (menuItemId == R.id.Water) {
                    if(waterFragment==null)
                        waterFragment = new WaterFragment();
                    getSupportFragmentManager().beginTransaction().replace(R.id.frame, waterFragment)
                            .commit();
                } else if (menuItemId == R.id.Advice) {
                    if(adviceFragment==null)
                        adviceFragment = new AdviceFragment();
                    getSupportFragmentManager().beginTransaction().add(R.id.frame, adviceFragment )
                            .commit();
                } else if (menuItemId == R.id.Diary) {
                    if(adviceFragment==null)
                        adviceFragment = new AdviceFragment();
                    getSupportFragmentManager().beginTransaction().add(R.id.frame, adviceFragment )
                            .commit();
                } else if (menuItemId == R.id.Help) {
                    if(adviceFragment==null)
                        adviceFragment = new AdviceFragment();
                    getSupportFragmentManager().beginTransaction().add(R.id.frame, adviceFragment )
                            .commit();
                }
                getFragmentManager().executePendingTransactions();

            }
        });