platform
RK3288 + Android 7.1 + AndroidStudio 4.0.1
problem
Use Handler
Handler.postDelayed(Runnable, Int)
When, the code in Runnable.run is not executed
analysis
Handler part of the code:
static class H extends Handler{
final static int MSG_REFRESH_TIME = 0;
WeakReference<KidsLauncher> a;
H(KidsLauncher lk){
a = new WeakReference<>(lk);
}
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case MSG_REFRESH_TIME:
a.get().refreshTime();
break;
}
}
/*@Override
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
Logger.d("sendmessageAtTime " + msg.what + " " + uptimeMillis + ":" + SystemClock.uptimeMillis());
return super.sendMessageAtTime(msg, uptimeMillis);
}*/
}
void refreshTime(){
tvTime.setText(TimeUtils.getTimeString());
h.removeMessages(H.MSG_REFRESH_TIME);
h.sendEmptyMessageDelayed(H.MSG_REFRESH_TIME, 1000);
}
Solutions tried:
- Use new Handler().postDelayed => the problem remains
- Use new Handler().postDelayed, delayed = 0 => the problem is solved, but it cannot be delayed
- Use Handler.post() => the problem is solved, but it cannot be delayed
- Use Handler.sendEmptyMessageDelayed => problem solved
- Use Handler.sendMessageDelayed => problem solved
- Use View.postDelayed => the problem remains
Check the relevant source code and articles:
Handler sendMessageDelayed()/postDelayed() mechanism in detail
Try to let go of the above comment code, output LOG, and finally found the problem.
solve
Reason: In the application, define a message type as MSG_REFRESH_TIME=0 ; after startup, the current time will be updated cyclically.
Consider the following question: After Handler.post, when finally enqueueMessage, what is Message. What ? The answer is 0
//frameworks/base/core/java/android/os/Handler.java
public final boolean postDelayed(Runnable r, long delayMillis)
{
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
Whether it is new Message() or Message.obtain(), at the beginning, it is basically 0
Look at the following code:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
h = new H(this);
h.postDelayed(new Runnable() {
@Override
public void run() {
Logger.d("run in post Delayed");
}
}, 2000);
h.removeMessages(0);
}
The LOG " run in post Delayed " in the code will not be printed out because the Message has been removed from the queue.
Similarly, after the update time of use MSG_REFRESH_TIME performed refreshTime, the queue, with all of the Message has been Runnable H. The removeMessages (H.MSG_REFRESH_TIME); out of the queue.
So the problem is, dig the hole yourself, then bury yourself...