Update Android UI from a thread in another class

前端 未结 3 662
轮回少年
轮回少年 2021-02-11 01:01

I\'ve seen a few questions on here asking similar questions, but I\'ve not yet seen a suitable answer. Many people have asked how to update the UI from a thread, but they\'re al

相关标签:
3条回答
  • 2021-02-11 01:27

    There are a couple of options. If you have access to the View you are changing and simply need to force a refresh, you can use View.postInvalidate() from any thread. If you need more complex operations, such as changing the text of a button, you should use runOnUIThread, which requires access to the Activity context. This should be simple to get - just add it as a parameter for your custom Object's constructor. With this context, you can do something like this:

    activityContext.runOnUiThread(new Runnable(){
        @Override
        public void run() {
            myButton.setText("disconnect");
        }
    });
    
    0 讨论(0)
  • 2021-02-11 01:28

    What I'm trying to do is update the UI from a thread which has been created in another class. I've seen all of the suggestions, such as async, handlers, runnable, etc... but I've having real trouble implementing them in separate classes.

    Generally for your goal i recommend to you use:

    • AsyncTask
    • IntentService with ResultReceiver

    I don't think that its too tricky. Absolutely not. If you have it as separated class(es) and not as inner class(es) in some Activity class so i recommend to use constructor where you will pass context, widgets, generally whatever you want and then in correct methods(which allows UI update) update your UI.

    I'm doing it because i like when i have clean classes(so UI class have only UI implementations and logic is positioned separately).

    Example:

    public class TaskExample extends AsyncTask<Void, Integer, Void> {
    
       private Context c;
       private Button b;
    
       public TaskExample(Context c, Button b) {
          this.c = c;
          this.b = b;
       }
    
       protected Void doInBackground(Void... params) {
          // some work
          if (isSomethingConnected) {
             publishProgress(Constants.IS_CONNECTED);
          }
          return null;
       }
    
       public void onProgressUpdate(Integer... params) {
           switch (params[0]) {
              case Constants.IS_CONNECTED:
                 b.setText("Connected");
              break;
              case Constants.ANOTHER_CONSTANT:
                 // another work
              break;
           }
       }  
    }
    

    Usage:

    public class Main extends Activity implements View.OnClickListener {
    
       private Button b;
    
       public void onCreate(Bundle b) {
          super.onCreate(b);
          // initialise widgets and set listeners to appropriate widgets
       }
    
       public void onClick(View v) {
          switch(v.getId()) {
             case R.id.connectBtn:
                startWorker();
             break;
          }
       }
    
       private void startWorker() {
          TaskExample te = new TaskExample(this, b);
          te.execute();
       }
    }
    
    0 讨论(0)
  • 2021-02-11 01:40

    Use the runOnUiThread(Runnable) method to run something on the Main thread and call the ClassName.View.invalidate() method if it is a view or just make a public method in you're Target class which handles the refreshing of the UI.

    0 讨论(0)
提交回复
热议问题