-1

I have seen a lot of similar questions about this issue but I couldn't find any solution to this:

I have three fragments in a TabLayout handled by a ViewPager and I have a ListView in the third Fragment which is not displaying any items after I change the orientation of the screen. I have tried to set a background color to the convertView in the ArrayAdapter to see if it was displayed and indeed it is not being displayed after I change the orientation. But it's weird because in my First Fragment where I use the same ArrayAdapter for another ListView everything's working and I can't understand why it's not on the third Fragment. One thing is sure: I have checked with logs almost everywhere that the ArrayList.size() is never zero.

Here's the Third Fragment's relevant code:

public class SavedScanFragment extends Fragment{

private ListView lv;
private Database db;
private ArrayList<Scan> scans;
private ScanAdapter adapter;

public static SavedScanFragment newInstance() {
    return new SavedScanFragment();
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    db = new Database(getContext());
    getScans();
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View result = inflater.inflate(R.layout.fragment_saved_scan, container, false);
    lv = (ListView) result.findViewById(R.id.saved_scan_list);
    return result;
}

@Override
public void onResume() {
    super.onResume();
    db = new Database(getContext());
    getScans();
}

public void getScans() {
    AsyncTask<Void, Void, Boolean> task = new AsyncTask<Void, Void, Boolean>() {
        @Override
        protected Boolean doInBackground(Void... params) {
            scans = db.getScans();
            if(scans!=null)
                return true;
            else {
                scans = new ArrayList<>();
                return false;
            }
        }

        @Override
        protected void onPostExecute(Boolean result) {
            if(result)
                populateList();
        }
    };
    task.execute();
}

public void populateList() {
    if(getContext()!=null) {
        if (lv.getAdapter() == null) {
            adapter = new ScanAdapter(getContext(), R.layout.scan_list_item, scans);
            lv.setAdapter(adapter);
        } else {
            ((ScanAdapter) lv.getAdapter()).update(scans);
        }
    }
}

And the ArrayAdapter's code:

public class ScanAdapter extends ArrayAdapter<Scan> implements ListAdapter {

private Context context;
private int layoutResourceID;
private ArrayList<Scan> results;

public ScanAdapter(Context context, int layoutResourceID, ArrayList<Scan> results) {
    super(context, layoutResourceID, results);
    this.context = context;
    this.layoutResourceID = layoutResourceID;
    this.results = results;
}

public void update(ArrayList<Scan> scans) {
    results.clear();
    results.addAll(scans);
    notifyDataSetChanged();
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View view = convertView; //view = row
    ViewHolder holder = null;
    if(view == null) {
        LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(layoutResourceID, parent, false);
        view.setBackgroundColor(Color.GREEN);
        holder = new ViewHolder();

            holder.name = (TextView)view.findViewById(R.id.scan_name_and_date_text);
            holder.ssid = (TextView)view.findViewById(R.id.scan_SSID_text);
            holder.frequency = (TextView)view.findViewById(R.id.scan_frequency_text);
            holder.level = (TextView)view.findViewById(R.id.scan_level_text);

        view.setTag(holder);
    } else
        holder = (ViewHolder) view.getTag();

    Scan sr = results.get(position);
    holder.name.setText(sr.getName()+" ( "+sr.getDate()+" )");
    holder.ssid.setText(sr.getSsid() + " ( " + sr.getBssid() + " )");
    holder.frequency.setText(sr.getFrequency()+" MHz");
    holder.level.setText(Integer.toString(sr.getLevel())+ " dBm");
    return view;
}

static class ViewHolder {
    TextView name,ssid, frequency, level;
}

}

Thanks in advance!

Automatik
  • 329
  • 1
  • 7
  • 15
  • So your problem happens when changing orientation, right? – T D Nguyen Mar 08 '16 at 00:15
  • yes, both landscape and portrait. If I start my app in portrait mode and I rotate to landscape my fragment listview is showing nothing and even after if I return to portrait it is showing nothing. So I think it's a problem after i change the screen orientation – Automatik Mar 08 '16 at 00:19
  • in your onResume() fill the adapter with new data and call notifyDataSetChanged() – XxGoliathusxX Mar 08 '16 at 00:22
  • @XxGoliathusxX it helped. I have added the following code: if(adapter!=null) adapter.update(scans); Now it's showing items after I rotate the screen but it takes a little while to reload. Is there way I could refresh faster? – Automatik Mar 08 '16 at 00:29
  • 1
    Rotation the phone causes a new lifecycle. So it all begins with onStart() again and goes over to onCreate() and onResume(). Like starting a new activity this take a while. I would recommend you firstly to store big datasets like your list for the adapter and everything else in onSaveInstanceState() and in your onCreate if you find them just do the most necessary things. dont build up everything from scratch. Moreover Im sure there are tutorials in www to get faster restarts. – XxGoliathusxX Mar 08 '16 at 00:36
  • Which ViewPagerAdapter are you using. FragmentStatePagerAdapter or FragmentPagerAdapter? – Sagar Trehan Mar 08 '16 at 00:41
  • @Sagar Trehan FragmentPagerAdapter but XxGoliathusxX solved the problem with rotation. Now I' m saving my dataset like Nguyen Doan Tung suggested – Automatik Mar 08 '16 at 00:47

1 Answers1

2

From this post. You can try to use onActivityCreated instead of onCreate. Try this:

public class SavedScanFragment extends Fragment{

//....to restore the saved state
@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    //Restore the fragment state here
    db = new Database(getContext());
    getScans();

}
//add this to save instant state
  @Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    //save your important variable here to outstate
}
}
Community
  • 1
  • 1
T D Nguyen
  • 7,054
  • 4
  • 51
  • 71