我使用睡眠时遇到了问题?

时间:2011-08-24 12:20:46

标签: java android multithreading

为什么在我的代码中,除了最后一次计数外,TextView不会占用。 结果就是:counter= 4

int i =0;

while (i< 5) {
    try {
        Thread.sleep((i*1000));
        mText.setText("counter"+ i);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    // mText does not show
    mText.setText("counter= "+ i);
    i = i +1;
} 

6 个答案:

答案 0 :(得分:3)

当您的应用程序休眠时,您正在阻止UI线程,因此屏幕不会重绘,因此在循环结束之前您不会看到文本更改。

  

用户界面线程

     

启动应用程序时,系统会创建一个名为的线程   申请的“主要”。主线程,也称为UI   线程,非常重要,因为它负责调度   事件到适当的小部件,包括绘图事件。它是   也是应用程序与运行交互的线程   Android UI工具包的组件。

     

例如,如果您触摸屏幕上的a按钮,则会显示UI线程   将触摸事件调度到窗口小部件,窗口小部件又设置它   按下状态并向事件队列发布无效请求。该   UI线程将请求出列并通知窗口小部件重绘   本身。

     

这种单线程模型可能会导致性能不佳,除非你的   应用程序正确实施。具体来说,如果一切都是   发生在一个线程中,执行诸如的长操作   UI线程上的网络访问或数据库查询将阻止   整个用户界面。不能发送任何事件,包括绘图   事件,而长期运作正在进行中。来自用户的   透视,应用程序显示挂起。更糟糕的是,如果用户界面   线程被阻止超过几秒钟(约5秒钟)   目前,用户被提出臭名昭着的“应用程序没有   响应“(ANR)对话框。

     

如果你想看看它有多糟糕,可以写一个简单的应用程序   使用一个按钮在其OnClickListener中调用Thread.sleep(2000)。   按钮将保持按下状态约2秒钟   回到正常状态。当发生这种情况时,它很容易   用户认为应用程序很慢。

     

总而言之,对应用程序的响应性至关重要   用于保持UI线程畅通无阻的UI。如果你有长期的操作   执行,你应该确保在额外的线程(背景   或工人线程)。

更多信息:
http://developer.android.com/resources/articles/painless-threading.html

这就是问题所在。 AsyncTask是(一)解决方案:

  

AsyncTask

     

AsyncTask可以正确,轻松地使用UI线程。这个班   允许执行后台操作并在UI上发布结果   线程,而不必操纵线程和/或处理程序。

     

异步任务由在a上运行的计算定义   后台线程,其结果发布在UI线程上。

http://developer.android.com/reference/android/os/AsyncTask.html

答案 1 :(得分:2)

首先,在睡觉前更改文本是个好主意。

其次,如果你在一个单独的线程中执行此操作,那么你可以在ui线程中操作一个小部件。试试这个:

而不是

mText.setText("counter"+ i); 

尝试

runOnUIThread( new Runnable() {
    public void run() {
        mText.setText("counter"+ i);
    }
});

此致  Stéphane

答案 2 :(得分:1)

“while(i <= 5)”将继续直到五。 另一个解决方案是使“i”1开始,而不是0。

这有帮助吗?

答案 3 :(得分:1)

使用for循环(在非UI线程内):

for (int i = 0; i < 5; i++}{
    try {
        Thread.sleep((i*1000));
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    runOnUIThread(new Runnable() {
        public void run() {
            mText.setText("counter"+ i);
        }
    });  
}

答案 4 :(得分:0)

这里的许多答案为您提供了实现您想要的所需信息,但可能很难理解。

我将在下面提出一种实现它的新方法,也许更容易。但我想强调一下,你应该了解人们写的内容,我的previuos帖子和至少来自@LAS_VEGAS的帖子。

这很简单:使用处理程序。

添加像

这样的数据成员

Handler handler = new Handler();

然后点击:

for (int i = 0; i < 5; i++}{
    handler.postDelayed( new Runnable() {
        public void run() {
            mText.setText("counter"+ i);
        }
    }, i * 1000 );  
}

我现在无法访问我自己的计算机,并担心由于在匿名内部类中使用非最终变量而无法编译。所以你也可以尝试在你的主java类中构建一个这样的命名内部类:

public class ButtonTimerThread implements Runnable
{
     privqte int i =0;

     public ButtonTimerThread( int i)
     {
           this.i = i;
     }//cons

     public void run()
     {
            mText.setText("counter"+ i);
     }//met
}//class

然后你单击监听器方法看起来像:

for (int i = 0; i < 5; i++}{
    handler.postDelayed( new ButtonTimerThread( i ), i * 1000 );  
}

由于您的处理程序将由UI线程创建,因此它将能够更新UI。处理程序提供了一个优势,即具有一个延迟机制,该机制不会阻止对您的单击操作做出反应的UI线程。

我希望这有帮助,  斯特凡

答案 5 :(得分:0)

通常,sleep()问题的良好解决方案涉及停止使用sleep()。阻止UI线程总是一个非常糟糕的主意。它使应用程序的UI无响应。

在您的情况下,您希望每秒运行一次事件。实现这一目标的正确方法是使用计时器。