【问题标题】:A contradictory in Thread's work in androidThread 在 android 中的工作自相矛盾
【发布时间】:2013-08-03 06:58:51
【问题描述】:

我尝试通过 TimerTask 更改 UI,但我认识到这是不可能的,因为 TimerTask 在后台线程中运行,并且不允许后台线程更改 UI。
现在我的问题是:我正在从 TimerTask 更改 ProgressBar 和 TextView,它适用于 ProgressBar,但不适用于 TextView。为什么我可以更改 ProgressBar?

为什么 ProgressBar 对此没有任何问题?

timer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            int time = playerTimer(time);

            progressbar.setProgress(time);
            playerTime.setText(time);

        }

    }, 0, 1000);

【问题讨论】:

    标签: android multithreading textview android-progressbar timertask


    【解决方案1】:

    这是因为当您在ProgressBar.java 的源代码中看到方法refreshProgress(int id, int progress, boolean fromUser) 时,您会看到进度条在当前线程本身即UI 线程内更新。如果它不是 UI 线程,那么进度条将使用 Runnable 进行更新。

    另外,如果您想从非 UI 线程更新一次 UI,那么您可以使用 runOnUIThread(Runnable action)

    【讨论】:

      【解决方案2】:

      并非所有 UI 操作都必须在主线程上完成。可以从另一个线程调用的那些在主线程上调度视图或视图树的布局和/或绘制。在实践中,尝试辨别哪些方法可以安全地从非 UI 线程调用,哪些方法不安全,这并不是一个好主意。

      要解决这个问题,您应该使用 AsyncTask 并从运行在 UI 线程上的回调内部执行所有 UI 操作:onPreExecute()onPostExecute()onProgressUpdate()

      【讨论】:

        【解决方案3】:

        由于setProgress 方法是同步的,它似乎被设计为从另一个线程调用。但是文档并没有明确说明。

        【讨论】:

          【解决方案4】:

          ProgressBar 类旨在使用它。这是执行此操作的代码:

            if (mUiThreadId == Thread.currentThread().getId()) {
                  doRefreshProgress(id, progress, fromUser, true);
              } else {
                  if (mRefreshProgressRunnable == null) {
                      mRefreshProgressRunnable = new RefreshProgressRunnable();
                  }
          
                  final RefreshData rd = RefreshData.obtain(id, progress, fromUser);
                  mRefreshData.add(rd);
                  if (mAttached && !mRefreshIsPosted) {
                      post(mRefreshProgressRunnable); //--posted to view's thread --
                      mRefreshIsPosted = true;
                  }
              }
          

          这是检查您是否在 UI 线程上。如果不是它在 UI 线程上发布一个可运行的。我的猜测是这种设计有助于它从多个地方更新progressBar。

          对于其他视图你必须做的:

          runonUiThread(new Runnable(){
          
           @Override
           public void run(){
             //--- change the view--
           }
          
          });
          

          【讨论】:

            猜你喜欢
            • 2021-04-13
            • 2015-06-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-05-05
            • 1970-01-01
            • 2022-12-04
            • 1970-01-01
            相关资源
            最近更新 更多