繁体   English   中英

Android 定时器更新 textview (UI)

[英]Android timer updating a textview (UI)

我正在使用计时器来创建秒表。 计时器通过增加 integer 值来工作。 然后我想通过不断更新 textview 在活动中显示这个值。

这是我尝试更新活动的 textview 的服务中的代码:

protected static void startTimer() {
    isTimerRunning = true; 
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            elapsedTime += 1; //increase every sec
            StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); //this is the textview
        }
    }, 0, 1000);
}

我在错误的线程中更新 UI 时遇到了某种错误。

如何调整我的代码以完成不断更新 textview 的任务?

protected static void startTimer() {
    isTimerRunning = true; 
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            elapsedTime += 1; //increase every sec
            mHandler.obtainMessage(1).sendToTarget();
        }
    }, 0, 1000);
}

public Handler mHandler = new Handler() {
    public void handleMessage(Message msg) {
        StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); //this is the textview
    }
};

上面的代码将工作...

注意:处理程序必须在您的主线程中创建,以便您可以修改 UI 内容。

您应该使用Handler每 X 秒更新一次 UI。 这是另一个显示示例的问题: 重复一个有时间延迟的任务?

您的方法不起作用,因为您正在尝试从非 UI 线程更新 UI。 这是不允许的。

StopWatch.time.post(new Runnable() {
    StopWatch.time.setText(formatIntoHHMMSS(elapsedTime));
});

此代码块基于 Handler,但您不需要创建自己的 Handler 实例。

您可以使用以下实用程序:

/**
 * Created by Ofek on 19/08/2015.
 */
public class TaskScheduler extends Handler {
    private ArrayMap<Runnable,Runnable> tasks = new ArrayMap<>();
    public void scheduleAtFixedRate(final Runnable task,long delay,final long period) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                task.run();
                postDelayed(this, period);
            }
        };
        tasks.put(task, runnable);
        postDelayed(runnable, delay);
    }
    public void scheduleAtFixedRate(final Runnable task,final long period) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                task.run();
                postDelayed(this, period);
            }
        };
        tasks.put(task, runnable);
        runnable.run();
    }
    public void stop(Runnable task) {
        Runnable removed = tasks.remove(task);
        if (removed!=null) removeCallbacks(removed);
    }

}

然后在由 UI 线程运行的代码中的任何地方,您都可以像这样简单地使用它:

TaskScheduler timer = new TaskScheduler();
        timer.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                time.setText(simpleDateFormat.format(GamePlay.instance().getLevelTime()));
            }
        },1000);

你可以使用处理程序。

此代码每秒增加一个计数器,并在textView显示和更新计数器值。

public class MainActivity extends Activity {


    private Handler handler = new Handler();
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.text);
        startTimer();
    }


    int i = 0;
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            i++;
            textView.setText("counter:" + i);
            startTimer();
        }
    };

    public void startTimer() {
        handler.postDelayed(runnable, 1000);
    }

    public void cancelTimer() {
        handler.removeCallbacks(runnable);
    }

    @Override
    protected void onStop() {
        super.onStop();
        handler.removeCallbacks(runnable);
    }
}

TimerTask 实现了 Runnable,这将使它成为一个线程。 如果不做一些工作,您无法直接从不同的线程更新主 UI 线程。 您可以做的一件事是使用 Async Task 创建计时器并每秒发布一次更新,以更新 UI。

我假设StopWatch.time是一些 static 或对您的 TextView 的公共引用。 而不是这样做,您应该实现BroadcastReceiver以在您的计时器(从单独的线程运行)和您的 TextView 之间进行通信。

我用这种方式:

String[] array = {"man", "for", "think"}; 
int j;

然后添加更多onCreate

TextView t = findViewById(R.id.textView);

new CountDownTimer(5000,1000) {

    @Override
    public void onTick(long millisUntilFinished) {}

    @Override
    public void onFinish() {
        t.setText("I " + array[j] + " You");
        j++;
        if (j == array.length - 1) j = 0;
        start();
    }
}.start();
 timer.schedule(new TimerTask() {
            @Override
            public void run() {

                //your actions

            }
        },1*1000);//1 sec

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM