Android 为什么Handler::postDelay使UI冻结
我有这个密码。我不知道为什么在这种情况下postDelay会使UI冻结。我希望Runnable将在100毫秒后运行,deley将在4000毫秒后运行Android 为什么Handler::postDelay使UI冻结,android,multithreading,Android,Multithreading,我有这个密码。我不知道为什么在这种情况下postDelay会使UI冻结。我希望Runnable将在100毫秒后运行,deley将在4000毫秒后运行 package com.delaythread; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android
package com.delaythread;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
public class MyNeedActivity extends Activity implements OnClickListener {
private ProgressBar progressBar;
private final Handler handler = new Handler() {
@Override
public void handleMessage(final Message msg) {
super.handleMessage(msg);
progressBar.setVisibility(ProgressBar.INVISIBLE);
}
};
@Override
public void onClick(final View v) {
if(v.getId() == R.id.button1) {
/* This call doesn't make ProgressBar frozen.
final Thread t = new Thread(new MyRunnable());
t.start();
progressBar.setVisibility(ProgressBar.VISIBLE);
*/
// This makes ProgressBar frozen in 4000 miliseconds.
final boolean b = handler.postDelayed(new MyRunnable(), 100);
if(b) {
progressBar.setVisibility(ProgressBar.VISIBLE);
}
}
}
/** Called when the activity is first created. */
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
((Button)findViewById(R.id.button1)).setOnClickListener(this);
progressBar = (ProgressBar)findViewById(R.id.progressBar1);
}
private class MyRunnable implements Runnable {
@Override
public void run() {
sleep();
}
private void sleep() {
try {
Thread.sleep(4000);
handler.sendEmptyMessage(0);
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
}
}
更新:实际上我想要的是AsyncTask在一段延迟时间后执行,所以我按照这个答案执行。他说我应该使用Handler和Runnable。据我所知,你要求你的
MyRunnable
在GUI线程(只有一个)上运行;但它唯一能做的就是睡眠,这会导致GUI线程冻结等待它
您不应该在GUI线程中执行复杂的计算(或睡眠)
您可能需要阅读更详细的描述。据我所知,您要求您的
MyRunnable
在GUI线程(只有一个)上运行;但它唯一能做的就是睡眠,这会导致GUI线程冻结等待它
您不应该在GUI线程中执行复杂的计算(或睡眠)
您可能需要阅读更详细的描述。您可能希望在主UI线程以外的其他线程上运行
MyRunnable
,因此需要为此启动一个常规线程,如
new Thread(new MyRunnable()).start();
而不是为此使用处理程序
,它将您的runnable排队,以便在主UI线程上执行
顺便说一句,出于此目的,使用将更合适。您可能希望在主UI线程以外的其他线程上运行您的
MyRunnable
,因此需要为此启动一个常规线程,如
new Thread(new MyRunnable()).start();
而不是为此使用处理程序
,它将您的runnable排队,以便在主UI线程上执行
顺便说一句,出于此目的,使用将更合适。您的进度条没有更新,因为您没有更新它!尝试使用(它在不同的线程上运行,但允许您更新UI元素)并在异步任务的onProgress方法中设置进度条的状态 或
只需在Android上执行此示例,您的进度条不会更新,因为您没有更新它!尝试使用(它在不同的线程上运行,但允许您更新UI元素)并在异步任务的onProgress方法中设置进度条的状态 或
只需在Android上执行此示例即可类处理程序的Android参考指出: […]创建新处理程序时,它将绑定到创建它的线程的线程/消息队列[…] 因此,在活动实例化时创建的处理程序应该在UI线程上运行,从而在执行Runnable时阻塞它 尝试创建一个新的线程类,在其中实例化处理程序。然后将Runnable从onClick()方法传递给它。要传回消息(例如更新进度条),可以使用UI线程上运行的另一个处理程序 你也可以通过看一看课堂来避免很多痛苦 附言:
可以通过Thread.sleep(100)调用在AsyncTaskdoInBackground()中延迟执行。要延迟UI线程级别的执行,可以在AsyncTask.onPreExecute()中执行相同的操作。类处理程序的Android参考指出: […]创建新处理程序时,它将绑定到创建它的线程的线程/消息队列[…] 因此,在活动实例化时创建的处理程序应该在UI线程上运行,从而在执行Runnable时阻塞它 尝试创建一个新的线程类,在其中实例化处理程序。然后将Runnable从onClick()方法传递给它。要传回消息(例如更新进度条),可以使用UI线程上运行的另一个处理程序 你也可以通过看一看课堂来避免很多痛苦 附言:
可以通过Thread.sleep(100)调用在AsyncTaskdoInBackground()中延迟执行。要延迟UI线程级别上的执行,您可以在AsyncTask.onPreExecute()中执行相同的操作。根据文章,以下内容应该适合您的需要
private final Handler handler = new Handler() {
@Override
public void handleMessage(final Message msg) {
super.handleMessage(msg);
//start Asyntask here. progress show/hide should be done in asynctaswk itself.
}
};
@Override
public void onClick(final View v) {
if(v.getId() == R.id.button1) {
final boolean b = handler.postDelayed(new MyRunnable() , 1000);
}
}
private class MyRunnable implements Runnable {
@Override
public void run() {
handler.sendmessage(0);
}
}
}
根据职位要求,以下内容应适合您的需要
private final Handler handler = new Handler() {
@Override
public void handleMessage(final Message msg) {
super.handleMessage(msg);
//start Asyntask here. progress show/hide should be done in asynctaswk itself.
}
};
@Override
public void onClick(final View v) {
if(v.getId() == R.id.button1) {
final boolean b = handler.postDelayed(new MyRunnable() , 1000);
}
}
private class MyRunnable implements Runnable {
@Override
public void run() {
handler.sendmessage(0);
}
}
}
试试这个:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//Code to be executed after desired seconds
}
}, seconds*1000);
这将在给定的秒数内冻结UI,并在run()中执行代码。尝试以下操作:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//Code to be executed after desired seconds
}
}, seconds*1000);
这将在给定的秒数内冻结UI,并在run()中执行代码。否,我希望Runnable在延迟时间后执行复杂的计算,而不是在UI线程中。这就是我创建Runnable的原因。@ernazm是对的,如果在Runnable中执行的操作与UI无关,那么使用处理程序可能不是最佳选择。不,我希望Runnable在延迟时间后执行复杂的计算,而不是在UI线程中。这就是我创建Runnable的原因。@ernazm是对的,如果在Runnable中执行的操作与UI无关,那么使用处理程序可能不是最佳选择。您能更详细地解释一下正在发生的事情和希望发生的事情吗?我希望Runnable进行长时间计算,但要经过一段延迟时间。所以我必须使用Handler::postDelay。Runnable计算时,ProgressBar可见。当它结束时,Runnable是不可见的。好吧,那到底发生了什么?实际上我想做一些类似于这个问题的事情。但是进度条冻结了(你想做什么?为什么在后台线程中需要延迟?你能更详细地解释一下发生了什么以及你想发生什么吗?我希望Runnable进行长时间的计算,但要经过一段延迟时间。因此我必须使用Handler::postDelay。Runnable计算时,ProgressBar可见。当它完成时,Runnable invisible.Ok,实际上发生了什么?实际上我想做一些类似于这个问题的事情。但是ProgressBar冻结了。:(你想做什么?为什么你需要在后台线程中进行延迟?如何在延迟时间后启动AsyncTask?这个问题的答案是: