【问题标题】:Struggling with upating my UI from Thread努力从 Thread 更新我的 UI
【发布时间】:2013-08-14 01:37:38
【问题描述】:

我已经尝试过 AsyncTask、Handler 和一个简单的线程来实现我想要做的事情,但我无法让它们中的任何一个工作,下面是我需要用来更新我的 UI 的逻辑......

public class GameProcessor extends Thread {

@Override
public void run() {

    for (Integer integer : sequence) {

        //set button state to pressed
        Console.getBottomLeft().getButton().setBackgroundResource(R.drawable.button_focused);

        try {
            sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //set button state to un-pressed

        try {
            sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    try {
        sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }


}

}

请不要回复,除了主线程之外,您无法从任何地方更新 UI,我已经知道这一点,并且需要一个解决方案来解决如何在更新 UI 的同时从后端循环一些值。据我所知, AsyncTask 和 Handler 不会有太大帮助。

任何帮助将不胜感激!

【问题讨论】:

  • 运行这个会发生什么?崩溃,或者用户界面根本不更新?你说的按钮状态是 Android Button 类实例吗?
  • @TenFour04 我更新了代码 sn-p。 Console.getxxx 行将返回一个 android.widget.Button 实例并尝试更新它的后台资源。此代码抛出 CalledFromWrongThreadException。
  • 您能告诉我们为什么在后台线程中循环某些值时绝对需要更新 UI,以及为什么不能在 UI 线程上执行此操作吗?我问是因为如果您向我们提供更多信息,我们可以以更好的方式为您提供帮助。

标签: android multithreading loops android-asynctask handler


【解决方案1】:

如果您了解 UI 线程,为什么不知道:

runOnUiThread(new Runnable() {
    public void run() {
        //set button state to un-pressed or pressed.. or whatever you want..
    }
});

我不明白你的问题

【讨论】:

    【解决方案2】:

    在您的 Activity (mHandler) 中创建一个成员 Handler 对象。每当你想从另一个线程更新你的 UI 时,调用

    mHandler.post(new Runnable(){
        public void run(){
            //update the button state
        }
    });
    

    Handler 会在 UI 线程中为你调用这个 run() 方法。

    这是简化的。您可能希望将 Runnables 创建为成员变量,这样您就不会一遍又一遍地重新创建相同的 Runnables。

    【讨论】:

    • Waza_Be 的解决方案是这个的一个稍微简单的版本,所以看看那个。
    【解决方案3】:
        If you want to loop through some valuse, while updating the UI at the same time, then you may consider using AsyncTask and may use this feature:
    
        protected void onProgressUpdate(Integer... progress) {
                 setProgressPercent(progress[0]);
             }
    
        And from :
        protected Long doInBackground(URL... urls) {
                     calculate value
                     publishProgress(value);
                  return totalSize;
             }
    
        This will keep on updating UI thread with intermediate values you send.
    
        In case you already know this and have tried and it does not solve your purpose, am sorry :)
    
    or you can try this:
    

    公共无效运行(){

            Console.post(new Runnable() {
                public void run() {
                    Console.getBottomLeft().getButton().setBackgroundResource(R.drawable.button_focused);
                }
            });
        }
    

    【讨论】:

    • 刚刚编辑了我的答案以在底部添加另一个代码。也许它可以帮助您解决问题。
    【解决方案4】:

    为了更新您的 UI 线程,您可以使用处理程序。下面是一个使用 AsyncTask 和 Handler 的简单示例:

        private static final String MESSAGE_KEY = "com.example.mypackage.MSGKEY";
        private static final int MESSAGE_AUTHENTICATING = 0;
        private static final int MESSAGE_AUTHENTICATED = 1;
    
        /**
         * This handler will update UI 
         * 
         */
        private final Handler handler = new Handler() {
            public void handleMessage(Message msg) {
                switch (msg.getData().getInt(MESSAGE_KEY)) {
                case MESSAGE_AUTHENTICATING:
                    hashstream_stream.setVisibility(View.GONE);
                    hashstream_progress.setVisibility(View.VISIBLE);
                    break;
                case MESSAGE_AUTHENTICATED:
                    hashstream_stream.setVisibility(View.VISIBLE);
                    hashstream_progress.setVisibility(View.GONE);
                    break;
                default:
                    break;
    
                }
            }
        };
    
        /**
        * This method should be used to update UI thread.
        * 
        * @param value
        */
        private void postMessage(int value) {
            Message msgObj = handler.obtainMessage();
            Bundle bundle = new Bundle();
            bundle.putInt(MESSAGE_KEY, value);
            msgObj.setData(bundle);
            handler.sendMessage(msgObj);
        }
    
        /**
         * AsyncTask Helper class as network op
         * 
         * 
         */
        private class StreamHashTagTask extends AsyncTask<Void, Void, Void> {
    
            @Override
            protected Void doInBackground(Void... params) {
    
                //Do actual operation in here
    
                return null;
            }
    
            @Override
            protected void onPostExecute(Void result) {
                super.onPostExecute(result);
    
                postMessage(MESSAGE_AUTHENTICATED);
            }
    
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
    
                postMessage(MESSAGE_AUTHENTICATING);
            }
    
            /**
             * If you need to update progress override onProgressUpdate() method.
             * Since I am indeterminate using progress bar as authentication time
             * cannot be calculated , I don't need update here
             */
    
        }
    

    【讨论】:

      【解决方案5】:

      你试过了吗?

      instanceOfActivity.runOnUiThread(new Runnable(){
          @Override
          public void run() {
              Console.getBottomLeft().getButton().setBackgroundResource(R.drawable.button_focused);
          }
      });
      

      但在这种情况下,我不建议您在另一个对象中使用活动。

      请使用上述界面:

      public interface INotifyChange {
           void notify(object value); // Example: void notify(int progress);
      }
      

      在您调用 GameProcessor

      的活动中
      INotifychange mNotifier;
      
      mNotifier = new INotifyChange() {
          @Override
          public void notify(object value) {
              runOnUiThread(new Runnable(){
                  @Override
                  public void run() {
                      //You can update your UI here.
                  }
              });
          }
      };
      

      // 还有你的GameProcessor

      private INotifyChange mNotifier;
      public GameProcessor(INotifyChange aNotifier) {
          mNotifier = aNotifier;
      }
      

      //要更新UI的地方,请调用

      mNotifier.notify(value);
      

      【讨论】:

        猜你喜欢
        • 2011-05-21
        • 2021-11-23
        • 1970-01-01
        • 1970-01-01
        • 2019-08-22
        • 2018-07-29
        • 2012-05-29
        • 2020-01-31
        • 1970-01-01
        相关资源
        最近更新 更多