1

I am facing an issue when my android app changing fragment or changing device position to landscape. The content in the listview will destory /delete. I have read up some information about it that i will need to save the content / data of the listview under "onSaveInstanceState" and use "onCreate" to put those saved content / data back into the listview when the fragment is been re-created. But i am not sure what to key in under the "onSaveInstnceState" part. Please do help me with this. From what i am read some said this is quite easy to overcome but for me, it seem to be a huge wall to overcome.

Below are the code. Some part have been changed.

public class Tab extends Fragment {

    ArrayList<ExpaneseModel> beta1;
    ListView listView;
    private static ExpansesCustomAdapter adapter;

    @Override
    public void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(savedInstanceState==null){

        }else{

        }
    }

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


        View rootview =  inflater.inflate(R.layout.tab2, container, false);

        Button Add = (Button)rootview.findViewById(R.id.btnAdd);

        listView=(ListView)rootview.findViewById(R.id.list);

        beta1= new ArrayList<>();

        listView.setAdapter(adapter);

        Add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final Dialog dialogsetting = new Dialog(getActivity());
                dialogsetting.requestWindowFeature(Window.FEATURE_NO_TITLE);
                dialogsetting.setContentView(R.layout.entry_input);
                final EditText one = (EditText)dialogsetting.findViewById(R.id.et_one);
                final EditText two = (EditText)dialogsetting.findViewById(R.id.et_two);
                Button ok = (Button)dialogsetting.findViewById(R.id.btnOK);
                Button cancel = (Button)dialogsetting.findViewById(R.id.btnCancel);

                ok.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
            dataModels.add(new ExpaneseModel(one.getText().toString(), two.getText().toString()));
                        adapter.notifyDataSetChanged();                       
                        dialogsetting.dismiss();
                    }
                });

                cancel.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        dialogsetting.dismiss();
                    }
                });
                dialogsetting.show();
            }

        });
        return rootview;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
       //I am not sure what code to type in here

    } }

Below is the ExpaneseModel:

public class ExpaneseModel {

String one;
String two;


public ExpaneseModel(String one, String two) {
    this.one=one;
    this.two=two;

}

public String getOne() {
    return one;
}

public String getTwo() {
    return two;
}}

Below is the Custom Adapter Class:

public class ExpansesCustomAdapter extends ArrayAdapter<ExpaneseModel> implements View.OnClickListener{

    private ArrayList<ExpaneseModel> dataSet;
    Context mContext;

    // View lookup cache
    private static class ViewHolder {
        TextView txtOne;
        TextView txtTwo;
    }

    public ExpansesCustomAdapter(ArrayList<ExpaneseModel> data, Context context) {
        super(context, R.layout.expanses_row_item, data);
        this.dataSet = data;
        this.mContext=context;

    }

    @Override
    public void onClick(View v) {

        int position=(Integer) v.getTag();
        Object object= getItem(position);
        ExpaneseModel dataModel=(ExpaneseModel) object;

    }

    private int lastPosition = -1;

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // Get the data item for this position
        ExpaneseModel dataModel = getItem(position);
        // Check if an existing view is being reused, otherwise inflate the view
        ViewHolder viewHolder; // view lookup cache stored in tag

        final View result;

        if (convertView == null) {

            viewHolder = new ViewHolder();
            LayoutInflater inflater = LayoutInflater.from(getContext());
            convertView = inflater.inflate(R.layout.expanses_row_item, parent, false);
            viewHolder.txtOne = (TextView) convertView.findViewById(R.id.one);
            viewHolder.txtTwo = (TextView) convertView.findViewById(R.id.two)

            result=convertView;

            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
            result=convertView;
        }

        Animation animation = AnimationUtils.loadAnimation(mContext, (position > lastPosition) ? R.anim.up_from_bottom : R.anim.down_from_top);
        result.startAnimation(animation);
        lastPosition = position;

        viewHolder.txtName.setText(dataModel.getName());
        viewHolder.txtType.setText(dataModel.getAmount());
        viewHolder.info.setOnClickListener(this);
        viewHolder.info.setTag(position);
        // Return the completed view to render on screen
        return convertView;
    }
}
GFr33d0m
  • 11
  • 3
  • I don't see where you create the adapter. Consider making the the arraylist static. Activities doesn't have to be destroyed when changing orientation: [How we can use onNewIntent() in any Activity?](https://stackoverflow.com/questions/8357200/how-we-can-use-onnewintent-in-any-activity) and [Activity restart on rotation Android](https://stackoverflow.com/questions/456211/activity-restart-on-rotation-android) – RonTLV Aug 29 '17 at 16:05

1 Answers1

0

The problem is when you back to a Fragment, onCreateView() will call. So everything can go wrong. I solve this issue by these steps:

  1. Save rootView variable as a class variable. So you have saved rootView.
  2. In onCreateView(), before rootview = inflater.inflate(R.layout.tab2, container, false);, check whether if rootView is null. And if it isn't, then return rootView.

This way fragment won't be recreated and nothing changes. Your final code should be like this:

public class Tab extends Fragment {

    ArrayList<ExpaneseModel> beta1;
    ListView listView;
    private static ExpansesCustomAdapter adapter;
    private View rootView;

    @Override
    public void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(savedInstanceState==null){

        }else{

        }
    }

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

        if (rootView != null)
            return rootView;
        rootview = inflater.inflate(R.layout.tab2, container, false);

        Button Add = (Button)rootview.findViewById(R.id.btnAdd);

        listView=(ListView)rootview.findViewById(R.id.list);

        beta1= new ArrayList<>();

        listView.setAdapter(adapter);

        Add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final Dialog dialogsetting = new Dialog(getActivity());
                dialogsetting.requestWindowFeature(Window.FEATURE_NO_TITLE);
                dialogsetting.setContentView(R.layout.entry_input);
                final EditText one = (EditText)dialogsetting.findViewById(R.id.et_one);
                final EditText two = (EditText)dialogsetting.findViewById(R.id.et_two);
                Button ok = (Button)dialogsetting.findViewById(R.id.btnOK);
                Button cancel = (Button)dialogsetting.findViewById(R.id.btnCancel);

                ok.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
            dataModels.add(new ExpaneseModel(one.getText().toString(), two.getText().toString()));
                        adapter.notifyDataSetChanged();                       
                        dialogsetting.dismiss();
                    }
                });

                cancel.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        dialogsetting.dismiss();
                    }
                });
                dialogsetting.show();
            }

        });
        return rootview;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
       //I am not sure what code to type in here

    } 
}
A. Badakhshan
  • 1,045
  • 7
  • 22
  • Thanks for the reply. the code i should add in will be the below? if (rootView != null) return rootView; – GFr33d0m Aug 30 '17 at 14:39
  • Yes and put declaration of rootView outside of onCreateView(). So, it will be saved. Let me know if it works. – A. Badakhshan Aug 31 '17 at 10:05
  • I have try your code. when i switch between fragment the listview will not be destory but when i check the device change to landscape, it got destory – GFr33d0m Sep 02 '17 at 06:14
  • yes if it stay in one orientation it works but if it changes the listview is re-created – GFr33d0m Sep 02 '17 at 18:29
  • Look at this and I think you will get the answer, Mark my answer if it's done. https://stackoverflow.com/questions/10634854/android-fragments-recreated-on-orientation-change. – A. Badakhshan Sep 03 '17 at 06:31