Простое приложение для приманки, и мне нужно, чтобы цикл возвращался к тому, что я должен повторять снова и снова [дублировать]

Это потому, что JVM хранит указатель на s1. Когда вы вызываете s2 = s1, вы в основном говорите, что указатель s2 (т. Е. Адрес памяти) имеет то же значение, что и для s1. Поскольку они оба указывают на одно и то же место в памяти, они представляют собой одно и то же.

Оператор = присваивает значения указателя. Он не копирует объект.

Объекты клонирования - это сложный вопрос сам по себе. У каждого объекта есть метод clone (), который может возникнуть у вас, но он делает мелкую копию (что в основном означает, что она делает копию объекта верхнего уровня, но любой объект, содержащийся в нем, не клонируется). Если вы хотите поиграть с копиями объектов, обязательно прочитайте Эффективное Java Джошуа Блоха

.

268
задан Community 25 April 2017 в 13:14
поделиться

18 ответов

ok, так как это не очищено, но есть 3 простых способа справиться с этим. Ниже приведен пример, показывающий все 3, а внизу - пример, показывающий только тот метод, который я считаю предпочтительным. Также не забудьте очистить свои задачи в onPause, сохраняя состояние при необходимости.


import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Handler.Callback;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class main extends Activity {
    TextView text, text2, text3;
    long starttime = 0;
    //this  posts a message to the main thread from our timertask
    //and updates the textfield
   final Handler h = new Handler(new Callback() {

        @Override
        public boolean handleMessage(Message msg) {
           long millis = System.currentTimeMillis() - starttime;
           int seconds = (int) (millis / 1000);
           int minutes = seconds / 60;
           seconds     = seconds % 60;

           text.setText(String.format("%d:%02d", minutes, seconds));
            return false;
        }
    });
   //runs without timer be reposting self
   Handler h2 = new Handler();
   Runnable run = new Runnable() {

        @Override
        public void run() {
           long millis = System.currentTimeMillis() - starttime;
           int seconds = (int) (millis / 1000);
           int minutes = seconds / 60;
           seconds     = seconds % 60;

           text3.setText(String.format("%d:%02d", minutes, seconds));

           h2.postDelayed(this, 500);
        }
    };

   //tells handler to send a message
   class firstTask extends TimerTask {

        @Override
        public void run() {
            h.sendEmptyMessage(0);
        }
   };

   //tells activity to run on ui thread
   class secondTask extends TimerTask {

        @Override
        public void run() {
            main.this.runOnUiThread(new Runnable() {

                @Override
                public void run() {
                   long millis = System.currentTimeMillis() - starttime;
                   int seconds = (int) (millis / 1000);
                   int minutes = seconds / 60;
                   seconds     = seconds % 60;

                   text2.setText(String.format("%d:%02d", minutes, seconds));
                }
            });
        }
   };


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

        text = (TextView)findViewById(R.id.text);
        text2 = (TextView)findViewById(R.id.text2);
        text3 = (TextView)findViewById(R.id.text3);

        Button b = (Button)findViewById(R.id.button);
        b.setText("start");
        b.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Button b = (Button)v;
                if(b.getText().equals("stop")){
                    timer.cancel();
                    timer.purge();
                    h2.removeCallbacks(run);
                    b.setText("start");
                }else{
                    starttime = System.currentTimeMillis();
                    timer = new Timer();
                    timer.schedule(new firstTask(), 0,500);
                    timer.schedule(new secondTask(),  0,500);
                    h2.postDelayed(run, 0);
                    b.setText("stop");
                }
            }
        });
    }

    @Override
    public void onPause() {
        super.onPause();
        timer.cancel();
        timer.purge();
        h2.removeCallbacks(run);
        Button b = (Button)findViewById(R.id.button);
        b.setText("start");
    }
}


главное помнить, что пользовательский интерфейс может быть изменен только из основного потока ui, поэтому используйте обработчик или активность. runOnUIThread (Runnable r);

Вот что я считаю предпочтительным.


import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class TestActivity extends Activity {

    TextView timerTextView;
    long startTime = 0;

    //runs without a timer by reposting this handler at the end of the runnable
    Handler timerHandler = new Handler();
    Runnable timerRunnable = new Runnable() {

        @Override
        public void run() {
            long millis = System.currentTimeMillis() - startTime;
            int seconds = (int) (millis / 1000);
            int minutes = seconds / 60;
            seconds = seconds % 60;

            timerTextView.setText(String.format("%d:%02d", minutes, seconds));

            timerHandler.postDelayed(this, 500);
        }
    };

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

        timerTextView = (TextView) findViewById(R.id.timerTextView);

        Button b = (Button) findViewById(R.id.button);
        b.setText("start");
        b.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Button b = (Button) v;
                if (b.getText().equals("stop")) {
                    timerHandler.removeCallbacks(timerRunnable);
                    b.setText("start");
                } else {
                    startTime = System.currentTimeMillis();
                    timerHandler.postDelayed(timerRunnable, 0);
                    b.setText("stop");
                }
            }
        });
    }

  @Override
    public void onPause() {
        super.onPause();
        timerHandler.removeCallbacks(timerRunnable);
        Button b = (Button)findViewById(R.id.button);
        b.setText("start");
    }

}


410
ответ дан Dave.B 15 August 2018 в 15:23
поделиться
  • 1
    Дэйв, спасибо за прекрасный ответ, это действительно помогает мне. – Dimon 26 November 2011 в 00:16
  • 2
    @Gautam Я считаю, что все вышеприведенные методы выполняют примерно то же самое. Я лично предпочитаю метод обработчика, описанный выше, с Run Runable и h2 Handler, поскольку он предписан для сайта разработчика Android и, на мой взгляд, также самый элегантный. – Dave.B 17 September 2012 в 20:23
  • 3
    Было бы неплохо, если бы ваш предпочтительный метод был отделен от остальной части кода. Например, у вас может быть один пример, показывающий ваш предпочтительный способ, а другой - альтернативы. Все три метода вместе усложняют понимание того, что происходит (особенно для новичков-андроидов, подобных мне). Наверное, слишком много спрашиваю :) – Jesse Aldridge 10 October 2013 в 23:30
  • 4
    @JesseAldridge Хорошая идея. Я пошел вперед и добавил код только с предпочтительным методом. – Dave.B 17 October 2013 в 18:29
  • 5
    Этот ответ противоположный прост ... – Egg 4 May 2014 в 04:24

Вот простой надежный способ ...

Поместите следующий код в свою активность, и метод tick () будет вызываться каждую секунду в потоке пользовательского интерфейса, пока ваша активность находится в «возобновленном» " государство. Конечно, вы можете изменить метод tick () для того, чтобы делать то, что вы хотите, или вызывать более или менее часто.

@Override
public void onPause() {
    _handler = null;
    super.onPause();
}

private Handler _handler;

@Override
public void onResume() {
    super.onResume();
    _handler = new Handler();
    Runnable r = new Runnable() {
        public void run() {
            if (_handler == _h0) {
                tick();
                _handler.postDelayed(this, 1000);
            }
        }

        private final Handler _h0 = _handler;
    };
    r.run();
}

private void tick() {
    System.out.println("Tick " + System.currentTimeMillis());
}

Для желающих код «_h0 = _handler» необходим для избегайте одновременного запуска двух таймеров, если ваша активность приостановлена ​​и возобновлена ​​в течение периода тика.

1
ответ дан Adam Gawne-Cain 15 August 2018 в 15:23
поделиться
  • 1
    Почему этот неудобный _h0 подход, а не removeCallbacks в onPause, как и все остальные? – ToolmakerSteve 12 September 2014 в 16:50

Если вы хотите просто запланировать обратный отсчет до времени в будущем с регулярными уведомлениями об интервалах на этом пути, вы можете использовать класс CountDownTimer , доступный с уровня API 1.

new CountDownTimer(30000, 1000) {

    public void onTick(long millisUntilFinished) {
        mTextField.setText("Seconds remaining: " + millisUntilFinished / 1000);
    }

    public void onFinish() {
        mTextField.setText("Done");
    }

}.start();
24
ответ дан Ahmed Hegazy 15 August 2018 в 15:23
поделиться
  • 1
    CountDownTimer имеет смысл только в том случае, если вы знаете, что хотите, чтобы он ушел после нескольких казней. Это не типичный, не особенно гибкий подход. Чаще всего таймер, который повторяется навсегда (который вы отменяете, когда больше не нужен) или обработчик, который запускается один раз, а затем снова запускается, если понадобится снова. См. Другие ответы. – ToolmakerSteve 12 September 2014 в 16:42
  • 2
    Вы совершенно правы. Из имени класса он предоставляет один таймер обратного отсчета времени, пока не закончится, и, конечно же, он использует Handler в своей реализации. – Ahmed Hegazy 13 September 2014 в 14:51
  • 3
    Как показывать миллисекунды? В формате SS:MiMi? благодаря – Ruchir Baronia 7 December 2015 в 13:38

Для тех, кто не может полагаться на Chronometer , я сделал класс утилиты из одного из предложений:

public class TimerTextHelper implements Runnable {
   private final Handler handler = new Handler();
   private final TextView textView;
   private volatile long startTime;
   private volatile long elapsedTime;

   public TimerTextHelper(TextView textView) {
       this.textView = textView;
   }

   @Override
   public void run() {
       long millis = System.currentTimeMillis() - startTime;
       int seconds = (int) (millis / 1000);
       int minutes = seconds / 60;
       seconds = seconds % 60;

       textView.setText(String.format("%d:%02d", minutes, seconds));

       if (elapsedTime == -1) {
           handler.postDelayed(this, 500);
       }
   }

   public void start() {
       this.startTime = System.currentTimeMillis();
       this.elapsedTime = -1;
       handler.post(this);
   }

   public void stop() {
       this.elapsedTime = System.currentTimeMillis() - startTime;
       handler.removeCallbacks(this);
   }

   public long getElapsedTime() {
       return elapsedTime;
   }

}

для использования.. просто делать:

 TimerTextHelper timerTextHelper = new TimerTextHelper(textView);
 timerTextHelper.start();

.....

 timerTextHelper.stop();
 long elapsedTime = timerTextHelper.getElapsedTime();
0
ответ дан Alécio Carvalho 15 August 2018 в 15:23
поделиться

Поскольку этот вопрос по-прежнему привлекает много пользователей из поиска Google (о таймере Android), я хотел бы вставить две мои монеты.

Прежде всего, Timer класс будет устаревшим в Java 9 (прочитайте принятый ответ) .

Предполагаемый способ official - использовать ScheduledThreadPoolExecutor , который является более эффективным и богатым функциональными возможностями, который может дополнительно планировать команды для запуска после определенной задержки или для выполнения периодически. Кроме того, это дает дополнительную гибкость и возможности ThreadPoolExecutor.

Вот пример использования простых функций.

  1. Создание службы-исполнителя:
    final ScheduledExecutorService SCHEDULER = Executors.newScheduledThreadPool(1);
    
  2. Просто запланировать выполнение:
    final Future<?> future = SCHEDULER.schedule(Runnable task, long delay,TimeUnit unit);
    
  3. Теперь вы можете использовать future для отмены задачи или проверить, выполнено ли это, например:
    future.isDone();
    

Надеюсь, вы найдете это полезным для создания задач в Android.

Полный пример:

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Future<?> sampleFutureTimer = scheduler.schedule(new Runnable(), 120, TimeUnit.SECONDS);
if (sampleFutureTimer.isDone()){
    // Do something which will save world.
}
6
ответ дан Community 15 August 2018 в 15:23
поделиться

Это просто! Вы создаете новый таймер.

Timer timer = new Timer();

Затем вы увеличиваете задачу таймера

class UpdateBallTask extends TimerTask {
   Ball myBall;

   public void run() {
       //calculate the new position of myBall
   }
}

, а затем добавляете новую задачу в таймер с некоторым интервалом обновления

final int FPS = 40;
TimerTask updateBall = new UpdateBallTask();
timer.scheduleAtFixedRate(updateBall, 0, 1000/FPS);

Отказ от ответственности: это не идеальное решение. Это решение, использующее класс Timer (по запросу OP). В Android SDK рекомендуется использовать класс Handler (есть пример в принятом ответе).

76
ответ дан fiction 15 August 2018 в 15:23
поделиться
  • 1
    если вы прочтете сообщение выше, вы поймете, почему это не идеальное решение – Dave.B 4 January 2011 в 21:06
  • 2
    Конечно. OP хотел сделать это с помощью TimerTask, который я не рекомендую использовать в игре. – fiction 4 January 2011 в 21:09
  • 3
    А? ОП не указал , как они хотели этого сделать. Они связаны со статьей, в которой используется TimerTask, но они не просили, чтобы это было сделано таким образом. – ToolmakerSteve 12 September 2014 в 17:22
  • 4
    Большое спасибо, спасибо @fiction – Naveed Ahmad 20 October 2015 в 12:04
  • 5
    отличный ответ прост для подражания. – JMASTER B 25 October 2015 в 21:31

Это простой код для таймера:

final int sekundi = 0 ;
Timer timer = new Timer();
TimerTask t = new TimerTask() {       
    @Override
    public void run() {

        System.out.println("1");
    }
};
timer.scheduleAtFixedRate(t,1000,1000);
14
ответ дан Freek Nortier 15 August 2018 в 15:23
поделиться
  • 1
    очень простой таймер ... – Jevgenij Kononov 23 June 2016 в 13:33
  • 2
    Какова цель переменной sec? – Freek Nortier 26 June 2018 в 13:00
  • 3
    Я хотел бы увеличить эту переменную sec variable.sec ++. Но потом я решил не делать этого. Это была простая функция таймера, чтобы продемонстрировать что-то ... – Jevgenij Kononov 27 June 2018 в 13:46

Если кому-то интересно, я начал играть с созданием стандартного объекта для запуска в потоке пользовательского интерфейса. Кажется, работает нормально. Комментарии приветствуются. Мне бы хотелось, чтобы это было доступно в дизайнере макетов в качестве компонента для перетаскивания на Activity. Не могу поверить, что подобное еще не существует.

package com.example.util.timer;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;

public class ActivityTimer {

    private Activity m_Activity;
    private boolean m_Enabled;
    private Timer m_Timer;
    private long m_Delay;
    private long m_Period;
    private ActivityTimerListener m_Listener;
    private ActivityTimer _self;
    private boolean m_FireOnce;

    public ActivityTimer() {
        m_Delay = 0;
        m_Period = 100;
        m_Listener = null;
        m_FireOnce = false;
        _self = this;
    }

    public boolean isEnabled() {
        return m_Enabled;
    }

    public void setEnabled(boolean enabled) {
        if (m_Enabled == enabled)
            return;

        // Disable any existing timer before we enable a new one
        Disable();

        if (enabled) {
            Enable();
        }
    }

    private void Enable() {
        if (m_Enabled)
            return;

        m_Enabled = true;

        m_Timer = new Timer();
        if (m_FireOnce) {
            m_Timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    OnTick();
                }
            }, m_Delay);
        } else {
            m_Timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    OnTick();
                }
            }, m_Delay, m_Period);
        }
    }

    private void Disable() {
        if (!m_Enabled)
            return;

        m_Enabled = false;

        if (m_Timer == null)
            return;

        m_Timer.cancel();
        m_Timer.purge();
        m_Timer = null;
    }

    private void OnTick() {
        if (m_Activity != null && m_Listener != null) {
            m_Activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    m_Listener.OnTimerTick(m_Activity, _self);
                }
            });
        }
        if (m_FireOnce)
            Disable();
    }

    public long getDelay() {
        return m_Delay;
    }

    public void setDelay(long delay) {
        m_Delay = delay;
    }

    public long getPeriod() {
        return m_Period;
    }

    public void setPeriod(long period) {
        if (m_Period == period)
            return;
        m_Period = period;
    }

    public Activity getActivity() {
        return m_Activity;
    }

    public void setActivity(Activity activity) {
        if (m_Activity == activity)
            return;
        m_Activity = activity;
    }

    public ActivityTimerListener getActionListener() {
        return m_Listener;
    }

    public void setActionListener(ActivityTimerListener listener) {
        m_Listener = listener;
    }

    public void start() {
        if (m_Enabled)
            return;
        Enable();
    }

    public boolean isFireOnlyOnce() {
        return m_FireOnce;
    }

    public void setFireOnlyOnce(boolean fireOnce) {
        m_FireOnce = fireOnce;
    }
}

В этой операции у меня есть это onStart:

@Override
protected void onStart() {
    super.onStart();

    m_Timer = new ActivityTimer();
    m_Timer.setFireOnlyOnce(true);
    m_Timer.setActivity(this);
    m_Timer.setActionListener(this);
    m_Timer.setDelay(3000);
    m_Timer.start();
}
0
ответ дан James Barwick 15 August 2018 в 15:23
поделиться
  • 1
    чувак, что случилось с ActivityTimerListener? Мой ADT Bundle сказал, что такого класса нет. – Sorokin Andrey 7 October 2013 в 11:42

Если у вас есть время дельта.

public class Timer {
    private float lastFrameChanged;
    private float frameDuration;
    private Runnable r;

    public Timer(float frameDuration, Runnable r) {
        this.frameDuration = frameDuration;
        this.lastFrameChanged = 0;
        this.r = r;
    }

    public void update(float dt) {
        lastFrameChanged += dt;

        if (lastFrameChanged > frameDuration) {
            lastFrameChanged = 0;
            r.run();
        }
    }
}
0
ответ дан Matthew Hooker 15 August 2018 в 15:23
поделиться

Если вам также нужно запустить свой код в потоке пользовательского интерфейса (а не по таймеру), посмотрите в блоге: http://steve.odyfamily.com/?p=12

public class myActivity extends Activity {
private Timer myTimer;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setContentView(R.layout.main);

    myTimer = new Timer();
    myTimer.schedule(new TimerTask() {          
        @Override
        public void run() {
            TimerMethod();
        }

    }, 0, 1000);
}

private void TimerMethod()
{
    //This method is called directly by the timer
    //and runs in the same thread as the timer.

    //We call the method that will work with the UI
    //through the runOnUiThread method.
    this.runOnUiThread(Timer_Tick);
}


private Runnable Timer_Tick = new Runnable() {
    public void run() {

    //This method runs in the same thread as the UI.               

    //Do something to the UI thread here

    }
};
}
57
ответ дан Meir Gerenstadt 15 August 2018 в 15:23
поделиться
  • 1
    Точно, что мне нужно - thx. – gcl1 26 September 2012 в 16:08
  • 2
    большое спасибо ,,, У меня много проблем с потоком пользовательского интерфейса с таймером, и вы исправлены им :) спасибо ♥ – Oubaida AlQuraan 2 February 2014 в 03:39
  • 3
    Ради полноты вы могли бы упомянуть, что делать, чтобы остановить таймер, и, возможно, перезапустить его. (Я нашел необходимую информацию здесь: stackoverflow.com/questions/11550561/… ) – RenniePet 25 April 2014 в 15:39
  • 4
    Есть ли причина, по которой вы не можете просто вызвать runOnUIThread непосредственно из метода запуска TimerTask? Кажется, что он отлично работает и удаляет другой уровень гнездования. – RichieHH 19 July 2014 в 23:06
  • 5
    Конечно, это всего лишь дидактический метод, чтобы понять все этапы. Я предлагаю этот стандарт иметь читаемый код. – Meir Gerenstadt 20 July 2014 в 12:58

Я удивлен, что нет ответа, который упоминал бы решение с RxJava2 . Это действительно просто и обеспечивает простой способ настройки таймера в Android.

Сначала вам нужно настроить зависимость Gradle, если вы этого не сделали:

implementation "io.reactivex.rxjava2:rxjava:2.x.y"

( замените x и y на текущий номер версии )

Поскольку у нас есть простая задача, не повторяющаяся, мы можем использовать объект Completable:

Completable.timer(2, TimeUnit.SECONDS, Schedulers.computation())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(() -> {
            // Timer finished, do something...
        });

Schedulers.computation() гарантирует, что наш таймер работает в фоновом потоке, а .observeOn(AndroidSchedulers.mainThread()) означает, что код, который мы запускаем после окончания таймера, будет выполнен в основном потоке.

2
ответ дан Micer 15 August 2018 в 15:23
поделиться
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

 CheckBox optSingleShot;
 Button btnStart, btnCancel;
 TextView textCounter;

 Timer timer;
 MyTimerTask myTimerTask;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  optSingleShot = (CheckBox)findViewById(R.id.singleshot);
  btnStart = (Button)findViewById(R.id.start);
  btnCancel = (Button)findViewById(R.id.cancel);
  textCounter = (TextView)findViewById(R.id.counter);

  btnStart.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View arg0) {

    if(timer != null){
     timer.cancel();
    }

    //re-schedule timer here
    //otherwise, IllegalStateException of
    //"TimerTask is scheduled already" 
    //will be thrown
    timer = new Timer();
    myTimerTask = new MyTimerTask();

    if(optSingleShot.isChecked()){
     //singleshot delay 1000 ms
     timer.schedule(myTimerTask, 1000);
    }else{
     //delay 1000ms, repeat in 5000ms
     timer.schedule(myTimerTask, 1000, 5000);
    }
   }});

  btnCancel.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    if (timer!=null){
     timer.cancel();
     timer = null;
    }
   }
  });

 }

 class MyTimerTask extends TimerTask {

  @Override
  public void run() {
   Calendar calendar = Calendar.getInstance();
   SimpleDateFormat simpleDateFormat = 
     new SimpleDateFormat("dd:MMMM:yyyy HH:mm:ss a");
   final String strDate = simpleDateFormat.format(calendar.getTime());

   runOnUiThread(new Runnable(){

    @Override
    public void run() {
     textCounter.setText(strDate);
    }});
  }

 }

}

.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity" >

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:autoLink="web"
    android:text="http://android-er.blogspot.com/"
    android:textStyle="bold" />
<CheckBox 
    android:id="@+id/singleshot"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Single Shot"/>

0
ответ дан Nepster 15 August 2018 в 15:23
поделиться
  • 1
    Я вижу, что вы добавили это через несколько лет после первоначального вопроса & amp; ответы. Пожалуйста, добавьте объяснение того, как этот ответ сравнивается с другими ответами, которые уже были там. Почему вы добавили еще одну - какую выгоду / когда полезно / что недостаток вы видели в других ответах? – ToolmakerSteve 12 September 2014 в 16:45
  • 2
    Я просто использую код, который выполняет ту же работу с другим подходом. Но всякий раз, когда вы хотите обновить данные любого вида. Вы должны использовать обработчик для этого. потому что много раз я заметил, что использование timertask для обновления представления не работает. @ Метод Dave.B является более правильным для моих знаний. – Nepster 15 September 2014 в 07:58

Вам нужно создать поток для обработки цикла обновления и использовать его для обновления текстового поля. Сложная часть состоит в том, что только основной поток может фактически изменить ui, поэтому поток цикла обновления должен сигнализировать основному потоку для обновления. Это делается с помощью Handler.

Проверьте эту ссылку: http://developer.android.com/guide/topics/ui/dialogs.html# Нажмите на раздел под названием «Пример ProgressDialog со вторым потоком». Это пример того, что вам нужно сделать, за исключением диалогового окна прогресса, а не текстового поля.

0
ответ дан Nick 15 August 2018 в 15:23
поделиться
  • 1
    Не делай этого. Существует простой класс таймера, который делает все это для вас. И этот вопрос не имеет ничего общего с progressdialogs или диалогами вообще. – Falmarri 4 January 2011 в 21:04
  • 2
    Вы посмотрели раздел ссылки, которую я опубликовал, или вы просто видите диалоговое окно слова и предполагаете? Код соответствует 100%. Также FYI, если вы используете таймер, вы все равно создаете поток для обработки цикла обновления. Вам все равно придется использовать обработчик, как описано в ссылке, которую я разместил. – Nick 4 January 2011 в 22:08
  • 3
    К сожалению, связанная страница больше не содержит раздел с указанным названием. При связывании с кодом всегда нужно включать ключевой фрагмент непосредственно в свой ответ. – ToolmakerSteve 12 September 2014 в 17:20

Вы хотите, чтобы ваши обновления пользовательского интерфейса выполнялись в уже существующем потоке пользовательского интерфейса.

Лучший способ - использовать обработчик, который использует postDelayed для запуска Runnable после задержки (каждый запуск расписания следующий) ; очистите обратный вызов с помощью removeCallbacks.

Вы уже смотрите в нужном месте, поэтому посмотрите на это снова, возможно, уточните, почему этот образец кода не тот, который вы хотите. (См. Также ту же статью в Обновление пользовательского интерфейса из таймера ).

2
ответ дан Risinek 15 August 2018 в 15:23
поделиться

Вот более простое решение, отлично работает в моем приложении.

  public class MyActivity extends Acitivity {

    TextView myTextView;
    boolean someCondition=true;

     @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.my_activity);

            myTextView = (TextView) findViewById(R.id.refreshing_field);

            //starting our task which update textview every 1000 ms
            new RefreshTask().execute();



        }

    //class which updates our textview every second

    class RefreshTask extends AsyncTask {

            @Override
            protected void onProgressUpdate(Object... values) {
                super.onProgressUpdate(values);
                String text = String.valueOf(System.currentTimeMillis());
                myTextView.setText(text);

            }

            @Override
            protected Object doInBackground(Object... params) {
                while(someCondition) {
                    try {
                        //sleep for 1s in background...
                        Thread.sleep(1000);
                        //and update textview in ui thread
                        publishProgress();
                    } catch (InterruptedException e) {
                        e.printStackTrace(); 

                };
                return null;
            }
        }
    }
2
ответ дан Rodion Altshuler 15 August 2018 в 15:23
поделиться

Вы также можете использовать для него аниматор:

int secondsToRun = 999;

ValueAnimator timer = ValueAnimator.ofInt(secondsToRun);
timer.setDuration(secondsToRun * 1000).setInterpolator(new LinearInterpolator());
timer.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
    {
        @Override
        public void onAnimationUpdate(ValueAnimator animation)
        {
            int elapsedSeconds = (int) animation.getAnimatedValue();
            int minutes = elapsedSeconds / 60;
            int seconds = elapsedSeconds % 60;

            textView.setText(String.format("%d:%02d", minutes, seconds));
        }
    });
timer.start();
0
ответ дан TpoM6oH 15 August 2018 в 15:23
поделиться
void method(boolean u,int max)
{
    uu=u;
    maxi=max;
    if (uu==true)
    { 
        CountDownTimer uy = new CountDownTimer(maxi, 1000) 
  {
            public void onFinish()
            {
                text.setText("Finish"); 
            }

            @Override
            public void onTick(long l) {
                String currentTimeString=DateFormat.getTimeInstance().format(new Date());
                text.setText(currentTimeString);
            }
        }.start();
    }

    else{text.setText("Stop ");
}
0
ответ дан WEFX 15 August 2018 в 15:23
поделиться
  • 1
    Может быть, некоторые отступы кода и объяснения кода были бы полезны. – Raul Rene 12 December 2012 в 16:03

Я думаю, вы можете сделать это с помощью Rx, например:

 timerSubscribe = Observable.interval(1, TimeUnit.SECONDS)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Action1<Long>() {
                @Override
                public void call(Long aLong) {
                      //TODO do your stuff
                }
            });

И отмените это как:

timerSubscribe.unsubscribe();

Rx Timer http: // reactivex. И.О. / документация / операторы / timer.html

7
ответ дан Will 15 August 2018 в 15:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: