通过实现 Runnable 更新时间

Updating time through implementation Runnable

我决定简化更新时间算法。通过Timer到处写算法。但是如果你在主activity中实现Runnable接口,你可以避免创建一个额外的对象。

打开激活就想要,时间每秒更新一次。但这不会发生。 根据我创建的标签 (ITTERATION),只有一次迭代。 使用 HERE

中的示例

我已经脑残了。 请帮助我:(

package pac.twoproject;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class Main2Activity extends AppCompatActivity implements Runnable {

    private static final String TAG = "ITTERATION";
    TextView tv;
    String time;

    final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");

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

        tv = (TextView) findViewById(R.id.textView);
        //scheduler.scheduleAtFixedRate(this, 0, 10, TimeUnit.MILLISECONDS);
    }

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

        scheduler.scheduleAtFixedRate(this, 0, 1000, TimeUnit.MILLISECONDS);
    }

    @Override
    public void run() {
        time = sdf.format(new Date(System.currentTimeMillis()));
        tv.setText(time);
        Log.d(TAG, time);
    }
}

我没有申请 android 但是... run() 正在按原样处理...
仅一次 除非您使用:

while (true) {
    time = sdf.format(new Date(System.currentTimeMillis()));
    tv.setText(time);
    Log.d(TAG, time);
}

您只能从应用程序的主线程(GUI 线程)修改 Views。在您的例子中,当 ScheduledExecutorService 调用 run 时,它将在不同的线程中执行。结果是 tv.setText(time); 抛出 CalledFromWrongThreadException。反过来,调度程序看到 Runnable 抛出异常,将抑制未来的执行:

Documentation for ScheduledExecutorService

If any execution of the task encounters an exception, subsequent executions are suppressed

有一个看似矛盾的东西需要解释:它只工作一次。这是因为您的初始延迟是 0。反过来,这意味着在调用 ScheduledExecutorService#scheduleAtFixedRate.

时,第一次执行可能是同步 运行

要解决此问题,您必须从主线程调用 tv.setText(time)。如何操作,可在 this question.

中找到

管理员帮助@WorldSEnder!谢谢! 出现异常 "android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views"。函数 scheduleAtFixedRate 调用的新线程无法更新文本字段中的文本。 通过Handler.

解决了问题

通过 Timer 来做更容易也更优化。 或者您知道如何优化它吗?

package pac.twoproject;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


public class Main2Activity extends AppCompatActivity implements Runnable {

    private static final String TAG = "ITTERATION";
    TextView tv;
    String time;
    Handler h;

    final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");

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

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

        h = new Handler() { //создаем наш хендл, в котором пропишем получение из очереди сообщения и обновление нашей переменной
            public void handleMessage(Message msg) {
                Bundle bundle = msg.getData(); // достаем их сообщение наш бондаж
                String text = bundle.getString("key"); // из бондажа уже наше сообщение
                tv.setText(text);
            }
        };

        scheduler.scheduleAtFixedRate(this, 0, 1000, TimeUnit.MILLISECONDS); // функция которая запускает метод ран в новом потоке и повторяем его запуск каждую секунду
    }


    @Override
    public void run() {

        try { // мониторим код
            time = sdf.format(new Date(System.currentTimeMillis())); // считываем время
            Log.d(TAG, time); // пишем его лог

            Message msg = Message.obtain(); // создаем новое сообщение
            Bundle bundle = new Bundle(); // создаем новый сверток (бандаж)
            bundle.putString("key", time); // в него пихаем по ключу наше время (текст)
            msg.setData(bundle); // и уже бондаж запихиваем в сообщение
            h.sendMessage(msg); //отправляем сообщение
        } catch (RuntimeException e) {
            Log.d(TAG, ""+ e);
        }
        Log.d(TAG, "1");
    }
}