【问题标题】:How to refresh a TextView while looping in Android?如何在 Android 中循环时刷新 TextView?
【发布时间】:2010-12-13 03:46:20
【问题描述】:

我有这个:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);


    TextView debugView = (TextView)findViewById(R.id.debugView);

    for(int i=0;i<100;i++) {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        debugView.setText(Integer.toString(i));
    }

}

我希望它每次通过循环更新文本视图,所以我会得到: 1, 2, 3, ... 99

相反,应用程序在 10 秒内什么都不做,然后输出:99

我猜我需要在循环期间刷新 TextView。我是 Android 开发的新手。有人可以告诉我这是否是完成此任务的最佳方法吗?

我的最终目标是能够处理音频样本以构建吉他调音器。我试图简单地从视觉上验证应用程序是否响应外部音频,并且我想更新一个 TextView 来证明这一点。请告知是否有更好的方法来做到这一点。

【问题讨论】:

  • 在 onCreate 返回之前什么都不会显示。

标签: android textview


【解决方案1】:

我遇到了同样的问题,我用处理程序解决了它:

public class myClass extends Activity{

 private Handler mHandler;
 private TextView text;
 private int i;

    @Override
      public void onCreate(Bundle savedInstanceState) {
          text = (TextView) findViewById(R.id.textView01);
          i = 0;
          mHandler = new Handler();
          mHandler.post(mUpdate);

      }

private Runnable mUpdate = new Runnable() {
   public void run() {

       text.setText("My number: " + i);
       i++;
       mHandler.postDelayed(this, 1000);

    }
};}

使用mHandler.post(mUpdate),您可以调用mUpdate,它是一个Runnable,它在可以更新UI 的不同线程中运行。在方法run() 中,不是创建一个与您的问题相同的for 循环,而是使用辅助变量设置您想要的文本,递增它并调用mHandler.postDelayed(this,updateTime)。在这一刻,视图更新,您的文本出现在屏幕上,并且在您指定的时间(以毫秒为单位)之后,将再次调用 Runnable mUpdate 并将文本设置为下一个数字,等等开。

我希望它有所帮助。

【讨论】:

    【解决方案2】:

    你最好使用计时器:

        new Timer().schedule(new TimerTask() {
    
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    public void run() {
                        debugView.setText("something");
                    }
                });
            }
        }, 0, 100);
    

    请注意,我使用的是runOnUiThread,因为您无法修改来自非主线程的另一个线程的视图。

    【讨论】:

    • 对于我的实际用例,我需要在一个循环中,因为我正在提取音频样本。我已经可以使用 Log.i() 显示输出。我只是在寻找一种简单的方法来将此信息显示到 Android 设备。我不在乎需要哪种类型的界面,或者即使我必须使用其中一个图形 UI 来绘制某些东西(如果它比在 TextView 上呈现更快)。如果您在循环时对如何执行此操作有任何建议,我将不胜感激。谢谢。
    • 请注意,Thread.sleep(100) 只是为了测试它,所以它不会走得太快以至于我错过了它。不过,我实际上并不希望有 100 毫秒的间隔。理想情况下,它应该尽可能快。
    • 在这种情况下,使用 AsyncTask。在 stackoverflow 或 Google 上有很多示例。
    • 您绝不能在 UI 线程中休眠或进行冗长的 I/O。直到您的各种方法(例如本例中的 onCreate)返回系统后,系统才能更新屏幕。 UI 线程中的所有方法都必须非常快速地执行并返回,否则您的应用程序将冻结或至少变得紧张。如果您需要提取音频样本,请启动另一个线程来处理它。其他线程可以使用消息来更新 UI。
    【解决方案3】:

    您的问题是您在 onCreate() 中运行循环。这发生在您的 Activity 显示之前的 UI 线程上。

    看看 Android 中的Activity lifecycle。它表明 onCreate 只是 Activity 创建的阶段之一。您要做的是在后台线程上运行循环并使用 runOnUiThread 发布通知以将 TextView 更新到 UI 线程。 Christian 的回答显示了如何做到这一点。

    但是,您的最终目标是根据一些用户输入(在您的情况下为音频)更新 TextView,您不必跳过所有这些循环即可使其正常工作。唯一重要的是您在 UI 线程上发布更新 UI 的调用,否则会出现异常。

    【讨论】:

    • out of oncreate 同样的问题。
    【解决方案4】:

    可以直接通过 Runnable 来查看 postDelayed,而不是使用 Handler:

    public class myClass extends Activity {
    
        private TextView text;
        private int i;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            text = (TextView) findViewById(R.id.textView01);
            text.postDelayed(mUpdate, 0);
    
        }
    
        private Runnable mUpdate = new Runnable() {
            public void run() {
    
                text.setText("My number: " + i);
                i++;
                text.postDelayed(this, 1000);
    
            }
        };
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-09
      • 1970-01-01
      相关资源
      最近更新 更多