ViewPager - как запускать разные таймеры на каждой странице?

Все, что я хочу, - это создать новый отдельный таймер для каждой страницы в ViewPager. Моя текущая реализация содержит один обработчик для всех страниц. Я запускаю новую TimerTask с помощью ViewPager.OnPageChangeListener.onPageSelected (), но, как я вижу во время работы моего приложения, стеки runnables и таймер работают все быстрее и быстрее, обновляя все текстовые представления одновременно, хотя я пытаюсь удалить все обратные вызовы в обработчик.

Как это должно работать: проведите пальцем до страницы 1 - таймер 1 запустится, проведите пальцем до страницы 2 - таймер 1 сбрасывается и останавливается, таймер 2 запускается и так далее.

viewPager.setOnPageChangeListener(new OnPageChangeListener() {

        public void onPageScrollStateChanged(int page) {

        }

        public void onPageScrolled(int position, float arg1, int arg2) {
        }

        public void onPageSelected(int position) {
            View currentPage = ((QuestionPagerAdapter) viewPager.getAdapter()).get(position);

            timerText = (TextView) currentPage.findViewById(R.id.timerText);
            handler.removeCallbacks(doTick);
            if (timerText != null) startTimer();
        }

    });

Работоспособная реализация:

final Runnable doTick = new Runnable() {

    public void run() {
        seconds--;
        if (seconds == -1) {
            minutes--;
            seconds = 59;
        }
        String secText = String.valueOf(seconds);
        if (seconds < 10) secText = "0" + secText;
        timerText.setText("0" + String.valueOf(minutes) + ":" + secText);
        viewPager.getAdapter().notifyDataSetChanged();
    }

};

private void startTimer() {
    for (int i = 1; i <= seconds; i++) {
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                handler.post(doTick);
            }
        };
        timer.schedule(task, i * 1000); 
    }
}

person sonderlain    schedule 07.11.2012    source источник


Ответы (1)


Где вы создаете экземпляр нового doTick Runnable? Это следует сделать только один раз, иначе вы не сможете удалить все обратные вызовы, связанные с экземпляром doTick, так как вы бы потеряли его и заменили новым экземпляром.

Объявите, что у него есть поле данных, и измените метод startTimer следующим образом:

private void startTimer( TextView textView ) {
    if( doTicks != null  ) {
       handler.removeCallbacks(doTick);
       doTicks = new doTicks( textView );
    }
    for (int i = 1; i <= seconds; i++) {
        TimerTask task = new TimerTask() {
            @Override
                public void run() {
                    handler.post(doTick);
                }
            };
        timer.schedule(task, i * 1000); 
    }
}

Вам также необходимо будет указать параметр для вашего doTicks Runnable, чтобы дать ему ссылку на поле, которое он должен обновить. Также передайте этот параметр в startTimer и не храните ссылку на это поле как на член данных действия, только как на член данных doTicks (так что вам нужно создать настоящий статический внутренний класс).

person Snicolas    schedule 07.11.2012
comment
Теперь все в порядке с textViews. Но есть одна вещь - таймеры складываются и секунды идут быстрее каждый раз, когда я пролистываю страницы, обратные вызовы, похоже, не удаляются. - person sonderlain; 08.11.2012
comment
Вы уверены, что вызываете removeCallBack для каждого экземпляра? Распечатайте в консоли свой запускаемый файл, они дадут вам свой адрес: печатайте их каждый раз, когда вы создаете его, и каждый раз, когда вы вызываете removecallbacks. Они должны совпадать. - person Snicolas; 08.11.2012
comment
Большое спасибо, но я еще не разобрался с этим. Я решил свою проблему, просто используя android.os.CountDownTimer, он вполне подошел. - person sonderlain; 08.11.2012