Android - 每5秒循环执行代码的部分

16

当我按下开始按钮时,我希望每5秒重复两行代码,并在我按下停止按钮时结束。我尝试使用TimerTask和Handles,但无法弄清楚如何做到这一点。

public class MainActivity extends Activity {




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


           //final int i;
           final TextView textView = (TextView) findViewById(R.id.textView);
           final Button START_STOP = (Button) findViewById(R.id.START_STOP);
           final ImageView random_note = (ImageView) findViewById(R.id.random_note);
           final int min = 0;
           final int max = 2;
           final Integer[] image = { R.drawable.a0, R.drawable.a1,R.drawable.a2 };



        START_STOP.setTag(1);
        START_STOP.setText("START");


        START_STOP.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
            int status = (Integer) v.getTag();
            if (status ==1) {
                textView.setText("Hello");
                START_STOP.setText("STOP");
                v.setTag(0);

                final Random random = new Random();

                                //************************************************************
                // I would like to loop next 2 lines of code every 5 seconds.//

                                int i = random.nextInt(2 - 0 + 1) + 0;
                random_note.setImageResource(image[i]);

                //************************************************************
                    }

            else
            {
                textView.setText("Bye");
                START_STOP.setText("Let's PLAY!");
                v.setTag(1);
            }


            }
        });     

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }


}

1
计时器任务有何问题未能正常工作? - FD_
我不知道。当我尝试在模拟器上运行它时,它崩溃了。但很可能是因为我做错了什么,因为我是一个Android(Java)初学者。 - Damijan
4个回答

34

使用CountDownTimer就像其他答案中所述一样是一种方法。另一种方法是使用Handler和postDelayed方法:

private boolean started = false;
private Handler handler = new Handler();

private Runnable runnable = new Runnable() {        
    @Override
    public void run() {
        final Random random = new Random();
        int i = random.nextInt(2 - 0 + 1) + 0;
        random_note.setImageResource(image[i]);
        if(started) {
            start();
        }
    }
};

public void stop() {
    started = false;
    handler.removeCallbacks(runnable);
}

public void start() {
    started = true;
    handler.postDelayed(runnable, 2000);        
}

这里是使用Timer和TimerTask的示例:

private Timer timer;
private TimerTask timerTask = new TimerTask() {

    @Override
    public void run() {
        final Random random = new Random();
        int i = random.nextInt(2 - 0 + 1) + 0;
        random_note.setImageResource(image[i]);
    }
};

public void start() {
    if(timer != null) {
        return;
    }
    timer = new Timer();
    timer.scheduleAtFixedRate(timerTask, 0, 2000);
}

public void stop() {
    timer.cancel();
    timer = null;
}

1
我一直在我的应用程序中使用CountDownTimer,比如每5秒钟更改活动中的横幅。重复某些操作每5秒钟的最佳方法是使用CountDownTimer还是Handler和postDelayed? - Giacomoni
谢谢。你会把它放在我的原始代码哪里? - Damijan
3
很好的问题giacomoni!我看了一下CountDownTimer,它在内部使用Handler:http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.0_r1/android/os/CountDownTimer.java#109 所以我猜它们差不多是等价的。而Timer则使用一个具有TimerTasks队列的TimerThread:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Timer.java#460 很难说哪个更好。我对线程和处理程序之间的区别不够了解,无法给您一个足够好的答案。 - britzl
1
@Damijan 将开始和停止方法放在您的活动中的某个位置。根据按钮状态从 onClick() 方法调用它们。将 TimerTask 或 Runnable 以及 Activity 的普通成员变量放在您的活动中。 - britzl

14
你可以使用以下方法来使用 CountDownTimer
private CountDownTimer timer;

timer = new CountDownTimer(5000, 20) {

    @Override
    public void onTick(long millisUntilFinished) {

    }

    @Override
    public void onFinish() {
        try{
            yourMethod();
        }catch(Exception e){
            Log.e("Error", "Error: " + e.toString());
        }
    }
}.start();

然后再次调用计时器:

public void yourMethod(){
    //do what you want
    timer.start();
}

要取消定时器,您可以调用timer.cancel();

希望这有所帮助!


您好,先生。以上代码能否用于在用户点击返回按钮之前刷新活动? - user6602265

7
您可以使用RxJava2/RxAndroid2创建一个Observable,它每秒发出一条消息(或者您想要的任何时间间隔),以下是伪代码示例:
Disposable timer = Observable.interval(1000L, TimeUnit.MILLISECONDS)
            .timeInterval()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<Timed<Long>>() {
                @Override
                public void accept(@NonNull Timed<Long> longTimed) throws Exception {               
                    //your code here.
                    Log.d(TAG, new DateTime());
                }
            });

当您想要停止它时,只需调用以下命令:
timer.dispose();

我发现这段代码比其他选项更易读。

0

除了提到使用Handler、CountDownTimer和普通计时器之间的差异之外,我没有更多要添加的了。正如britzl所提到的那样,CountDownTimer在内部使用Handler,因此使用该计时器相当于直接使用Handler。处理程序用于运行Ui内容,仅用于非常短的时间。一个例子是setText用于文本视图。对于计算密集型任务,处理程序可能会导致延迟。计时器也只能运行短任务,但它不一定只用于UI内容。对于更复杂的任务,应该使用新线程。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接