我决定简化更新时间算法。无处不在通过计时器编写算法。但是,如果在主活动中实现 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);
}
}
答案 0 :(得分:0)
您只能从应用程序的主线程(GUI线程)修改View
。在您的情况下,当ScheduledExecutorService
调用run
时,它将在另一个线程中执行此操作。结果是tv.setText(time);
抛出CalledFromWrongThreadException
。反过来,调度程序看到Runnable
引发了异常,将抑制未来的执行:
Documentation for ScheduledExecutorService
如果任务的任何执行遇到异常,则后续执行被禁止
有一个看似矛盾的东西需要解释:它有效一次。这是因为您的初始延迟为0
。反过来,这意味着在调用ScheduledExecutorService#scheduleAtFixedRate
时可以同步运行第一次执行。
要解决此问题,您必须从主线程中调用tv.setText(time)
。如何执行此操作,可以在this question中找到。
答案 1 :(得分:0)
管理员帮助 @WorldSEnder !谢谢! 有一个异常" android.view.ViewRootImpl $ CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触及其视图" 。函数 scheduleAtFixedRate 调用的新线程无法更新文本字段中的文本。 通过处理程序解决了这个问题。
通过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");
}
}
答案 2 :(得分:-1)
我不适用于android但是...... run()
正在处理,因为它是...
仅一次,除非您使用:
while (true) {
time = sdf.format(new Date(System.currentTimeMillis()));
tv.setText(time);
Log.d(TAG, time);
}