Активность с использованием ViewPager, PagerAdapter и AsyncTask вызывает пустое представление - PullRequest
6 голосов
/ 02 марта 2012

Я пытаюсь создать действие, которое будет служить представлением календарного дня. Когда пользователь проведет пальцем влево или вправо, он перейдет к завтрашнему или вчерашнему дню и т. Д. В календаре.

Я решил использовать ViewPager / PagerAdapter для обработки представлений и управления поиском по дням.

В рамках настройки Day View приложение перейдет к моему API и запросит любые встречи на этот день. Встречи будут возвращены и отображены на этот день. Для получения данных из API я использую AsyncTask. В общем, instantiateItem() вызывает API и устанавливает пустой listView. Затем BroadcastReceiver перехватывает ответ, анализирует данные и отображает их.

Проблема, с которой я столкнулся, заключается в том, что первый отображаемый вид всегда пуст. Виды слева или справа заполнены, и если я перейду на две позиции в любом направлении, достаточно для исходного вида чтобы уничтожить, а затем вернуться к исходному виду, у него есть данные. Почему? Как сделать так, чтобы первый вид заполнялся, не перемещаясь более чем на 2 пролистывания?

Вот моя деятельность. В настоящее время я не анализирую данные, возвращающиеся из API, а просто симулирую со списком строк за это время.

public class MyPagerActivity extends Activity {

    private ViewPager myPager;
    private static int viewCount = 1000;
    private Context ctx;
    private MyPagerAdapter myAdapter;

    private static final String tag = "MyPagerActivity";

    private static final String apiAction = "getAppointmentsForDate"; 
    private static final String apiUri = "https://myAPI.com/api.php";
    private static final String resource = "appointments";
    private static final String action = "getappointmentsfordate";
    private static final String date = "20120124";
    private ProgressDialog progress;
    private SharedPreferences loginPreferences;
    private SharedPreferences.Editor loginPreferencesEditor;
    private ListView v;

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

        myAdapter = new MyPagerAdapter();
        myPager = (ViewPager) findViewById(R.id.myPager);
        myPager.setAdapter(myAdapter);
        myPager.setCurrentItem(500);
    }

    private class MyPagerAdapter extends PagerAdapter {


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

        @Override
        public Object instantiateItem(View collection, int position) {

            try {
                Log.d(tag, "trying http connection");
                loginPreferences = getSharedPreferences("loginPrefs", MODE_PRIVATE);
                loginPreferencesEditor = loginPreferences.edit();
                String authToken = loginPreferences.getString("authToken", "");
                String staffOrRoomsId = loginPreferences.getString("staffOrRoomsId", "");
                String staffOrRoomsIdName = loginPreferences.getString("staffOrRoomsIdName", "");

                HttpPost apiRequest = new HttpPost(new URI(apiUri));
                List<NameValuePair> parameters = new ArrayList<NameValuePair>();
                parameters.add(new BasicNameValuePair("authToken", authToken));
                parameters.add(new BasicNameValuePair("resource", resource));
                parameters.add(new BasicNameValuePair("action", action));
                parameters.add(new BasicNameValuePair("date", date));
                parameters.add(new BasicNameValuePair(staffOrRoomsIdName, staffOrRoomsId));
                apiRequest.setEntity(new UrlEncodedFormEntity(parameters));

                RestTask task = new RestTask(ctx, apiAction); 
                task.execute(apiRequest); 
                //Display progress to the user 
    //            progress = ProgressDialog.show(ctx, "Searching", "Waiting For Results...", true); 
            } catch (Exception e) { 
                e.printStackTrace(); 
            } 

            Log.d(tag, "Creating another view! Position: " + position);

            myPager.setTag(collection);

            v = new ListView(ctx);
            ((ViewPager) collection).addView(v, 0);
            return v;
        }

        @Override
        public void destroyItem(View collection, int position, Object view) {
            Log.d(tag, "Destroying position: " + position + "!");
            ((ViewPager) collection).removeView((ListView) view);
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view==((ListView)object);
        }

        @Override
        public void finishUpdate(View arg0) {}

        @Override
        public void restoreState(Parcelable arg0, ClassLoader arg1) {}

        @Override
        public Parcelable saveState() {
            return null;
        }

        @Override
        public void startUpdate(View arg0) {}
    }

    @Override 
    public void onResume() { 
        super.onResume(); 
        registerReceiver(receiver, new IntentFilter(apiAction));  
    } 

    @Override 
    public void onPause() { 
        super.onPause(); 
        unregisterReceiver(receiver); 
    }

    private BroadcastReceiver receiver = new BroadcastReceiver() { 
        @Override 
        public void onReceive(Context context, Intent intent) { 
            //Clear progress indicator 
            if (progress != null) { 
                progress.dismiss(); 
            }

            Log.d(tag, "Broadcast received");

            String[] from = new String[] { "str" };
            int[] to = new int[] { android.R.id.text1 };
            List<Map<String, String>> items = new ArrayList<Map<String, String>>();
            for (int i = 0; i < 20; i++)
            {
                Map<String, String> map = new HashMap<String, String>();
                map.put("str", String.format("Item %d", i + 1));
                items.add(map);
            }
            SimpleAdapter adapter = new SimpleAdapter(ctx, items, android.R.layout.simple_list_item_1, from, to);
            v.setAdapter(adapter);
        } 
    };
}

Спасибо, что нашли время, чтобы рассмотреть этот вопрос!

1 Ответ

4 голосов
/ 15 марта 2012

По умолчанию ViewPager загружает не только видимую в данный момент страницу, но и страницу в любую сторону. Это offscreenPageLimit. Минимальное значение 1.

instantiateItem будет вызываться для каждой страницы, которую он хочет создать. В вашей реализации instantiateItem вы запускаете AsyncTask и присваиваете значение v. Только последний вызов instantiateItem (т.е. последняя страница до offscreenPageLimit) будет иметь правильное назначение v, и поэтому первая страница не будет заполнена изначально.

Вы не можете рассчитывать на последний вызов instantiateItem, чтобы указать вам на текущую активную страницу. Я бы переключился на использование фрагмента для каждой страницы, который поддерживает свой собственный HTTP-запрос и ListView.

...