r2DoesInc
r2DoesInc

Reputation: 3771

ViewPager, ListView, and AsyncTask, first page blank, all data in the second page

There is a similar question here, Activity using ViewPager, PagerAdapter and AsyncTask causes a blank view, but my problem is more than that.

I have a ViewPager that contains a ListView. This ListView is populated by an asyncTask. The listview displays the data, but not correctly. The first page is always blank, and the second page contains BOTH pages data.

I've simplified my asynctask to be sure tit wasnt something there that was causing the issue.

@Override
public Object instantiateItem(View pager, int position){
   // Log.d("PAGER", Integer.toString(position));
   ctx = pager.getContext();
   v = new ListView(ctx);
   new CreateArrayListTask().execute(URLS[position]);
   ((ViewPager)pager).addView(v, 0); 
   return v;
}

CreateArrayListTask

private class CreateArrayListTask extends AsyncTask<String, Void, ArrayList<String>> {               
   @Override
   protected ArrayList<String> doInBackground(String... params) {
     linkArray.add("Item 1");
     linkArray.add("Item 2");
     return linkArray;
   }

onPostExecute

protected void onPostExecute(ArrayList<String> linkArray) {
   ArrayAdapter<String> a = new ArrayAdapter<String>(ctx, android.R.layout.simple_list_item_1, linkArray);
   v.setAdapter(a);

enter image description here

Upvotes: 1

Views: 3347

Answers (1)

antonyt
antonyt

Reputation: 21883

The ListView on the second page is doubly populated precisely because of my answer given in the other question.

You are assuming instantiateItem will be called only for the currently active page, whereas it will actually be called to preload for offscreen pages too. The reference v to the view will be overwritten by the second call to instantiateItem.

Have a look at this example project to see one way how to do it with fragments: https://github.com/antonyt/ListFragmentViewPagerExample/tree/master/src/com/example/listfragment

Activity:

public class ListFragmentViewPagerActivity extends FragmentActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ViewPager pager = (ViewPager) findViewById(R.id.pager);
        pager.setAdapter(new ExamplePagerAdapter(getSupportFragmentManager()));
    }

    public class ExamplePagerAdapter extends FragmentPagerAdapter {

    public ExamplePagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        return 5;
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment = new ExampleListFragment();

        // set arguments here, if required
        Bundle args = new Bundle();
        // args.put(...)
        fragment.setArguments(args);

        return fragment;
    }
    }
}

Fragment:

public class ExampleListFragment extends ListFragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
     // normally you should inflate a view here and save references
    // using ListFragment default layout for this example
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public void onStart() {
        super.onStart();
        new CreateArrayListTask().execute();
    }

    private class CreateArrayListTask extends AsyncTask<String, Void, ArrayList<String>> {
    @Override
    protected ArrayList<String> doInBackground(String... params) {
        ArrayList<String> linkArray = new ArrayList<String>();
        linkArray.add("Item 1");
        linkArray.add("Item 2");
        return linkArray;
    }

    protected void onPostExecute(ArrayList<String> linkArray) {
        ArrayAdapter<String> a = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, linkArray);
        setListAdapter(a);
    }
    }

}

Upvotes: 1

Related Questions