【问题标题】:Updating the main thread is not working更新主线程不起作用
【发布时间】:2014-11-23 12:54:41
【问题描述】:

我只想显示延迟 2 秒的循环中每次迭代的值。

当我运行代码时,主线程冻结,一段时间后只显示tv_t1: 19 的值。

谁能告诉我下面发布的代码中的错误或我遗漏了什么?

注意

我想在主线程上这样做。

*代码

tv_t1 = (TextView) findViewById(R.id.tv_t1);
    tv_t2 = (TextView) findViewById(R.id.tv_t2);

    for(int i = 0; i < 20; i++) {
        tv_t1.setText("t1:" + i);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

【问题讨论】:

    标签: java android multithreading thread-safety runnable


    【解决方案1】:

    Thread是Android的main/UI线程,设置sleep(value)会导致主线程休眠或 在预定的时间停止工作。如果您想暂时更新main UIsleep,最好创建一个新的thread,然后创建覆盖Run()Runnable 对象。在Run() 内部,您可以调用耗时的函数,也可以将您创建的新thread 设置为sleep,而不是将UI thread 强制为sleep,这将导致所有主要的UI要冻结的元素。下面代码中的Handler 充当threadmessage queue 之间的中间体,您也可以将h1 替换为tv_1,以将其作为消息发布到队列中,然后更新您的视图。

    请尝试以下代码:

    Handler h1 = new Handler();
    Thread t1;
    
    t1 = new Thread(new Runnable() {
    
            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    loop();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
        t1.start();
    
    
        protected void loop() throws InterruptedException {
        // TODO Auto-generated method stub
         for (i = 0; i < 20; i++) {
             t1.sleep(2000);
             h1.post(new Runnable() {
    
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    tv_t1.setText("tv_1: " + i);
                }
            });
         }
    }
    

    【讨论】:

      【解决方案2】:

      UI 线程上的 Thread.sleep 是个坏主意。使用处理程序:

      private Handler mHandler = new Handler():
      private class MyRunnable implmenets Runanble {
         private final static int MAX_INT = 20;
         private int mCounter = 0;
      
               @Override
               public void run() {
               if (mCounter == 20) {
                   mHandler.removeCallbacks(this);
                   return; 
               }
               mytexts.setText(" " + mCounter);
               mCounter++;
               mHandler.postDelayed(this, 2000);
           }
      }
      

      在你的创建中,在你初始化你的视图之后,调用

      mHandler.postDelayed(new MyRunnable(), 2000);
      

      【讨论】:

      • 谢谢,但我想在主线程上做,可以吗
      • 好的,我不了解您的代码,但是请您提供一些解释,为什么我发布的代码不起作用?当我运行它时,屏幕不显示任何内容,过了一会儿它只显示“tv_1:19”
      • UI Thread 负责绘制视图。如果你让它睡觉它应该怎么画?
      • 好的,也许在休眠定时器结束后,ui线程继续绘制视图!
      【解决方案3】:

      也许这会解决:

      for(int i = 0; i < 20; i++) {
        new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
        tv_t1.setText("t1:" + i);
        }
      }, 2000);
      }
      

      是的,如果在“i”的值为 0 时出现延迟,则将第一个文本设置在循环之外并以 i=1 开始循环,或者在循环内放置一个 if-else 块

      希望对您有所帮助。

      【讨论】:

      • 谢谢,但我想在主线程上做,可以吗
      • 你试过运行我的答案吗?都是主线程,不用担心
      • 好的,我不了解您的代码,但是请您提供一些解释,为什么我发布的代码不起作用?当我运行它时,屏幕不显示任何内容,过了一会儿它只显示“tv_1:19”
      • 记住一件事,伙计,我们从不冻结主线程,我认为 TextView 需要一些时间来执行和显示,同时主线程再次进入睡眠状态,你无法看到结果,当最后一个值被更新时,只有你能看到结果
      • 但我认为睡眠定时器结束后,ui线程应该继续绘制视图!
      猜你喜欢
      • 2016-03-21
      • 2018-01-30
      • 1970-01-01
      • 2018-03-06
      • 2014-04-30
      • 1970-01-01
      • 2019-02-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多