Android Thread modify EditText

2019-02-18 23:28发布

问题:

I am having a problem with modifying EditText in another function started by the thread:

Thread thRead = new Thread( new Runnable(){
    public void run(){
       EditText _txtArea = (EditText) findViewById(R.id.txtArea);
       startReading(_txtArea);
    }
 });

my function is as follows:

public void startReading(EditText _txtArea){
         _txtArea.setText("Changed");
}

It always force closes while trying to modify the edittext. Does someone know why?

回答1:

UI views should not be modified from non-UI thread. The only thread that can touch UI views is the "main" or "UI" thread, the one that calls onCreate(), onStop() and other similar component lifecycle function.

So, whenever your application tries to modify UI Views from non-UI thread, Android throws an early exception to warn you that this is not allowed. That's because UI is not thread-safe, and such an early warning is actually a great feature.


UPDATE:

You can use Activity.runOnUiThread() to update UI. Or use AsyncTask. But since in your case you need to continuously read data from Bluetooth, AsyncTask should not be used.

Here is an example for runOnUiThread():

runOnUiThread(new Runnable() {            
    @Override
    public void run() {
        //this will run on UI thread, so its safe to modify UI views.
         _txtArea.setText("Changed");
    }
});


回答2:

First of all take a look at your log, it usually contains a stack trace when an app shuts down.

You shouldn't run the thread like you normally do, instead use runOnUiThread:

Runnable thRead = new Runnable(){
   public void run() {
      EditText _txtArea = (EditText) findViewById(R.id.txtArea);
      startReading(_txtArea);
   }
};
runOnUiThread(thRead);

The explaination: Only the UI thread is allowed to change the state of UI components.



回答3:

This article may help you.

http://android-developers.blogspot.com/2009/05/painless-threading.html

There are few options:
1. run it on UI thread Activity.runOnUiThread(Runnable)
2. use AsyncTask



回答4:

Except runOnUiThread() (which works), there is also another way, which I know of:

Define a handler in your UI (Activity) class:

public class MainActivity extends Activity {

.....

    Handler uiThreadHandler = new Handler() {
        public void handleMessage(Message msg) {
            Object o = msg.obj;
            if (o==null) o = "";
            TextView textIn = (TextView)findViewById(R.id.textin);
            textIn.setText(o.toString());
        }
    };

}

and from inside some thread you can call it:

Message msg = uiThreadHandler.obtainMessage();
msg.obj = "Text for EditView";
uiThreadHandler.sendMessage(msg);


回答5:

By default, the main thread is the UI thread. All code that modifies the appearance of the application needs to be run in this thread. If you want to have multiple threads in your application that can modify the UI I would suggest using the AsyncTask class.

public someMethod(){
    new ChangeTextTask().execute();
}

private class ChangeTextTask extends AsyncTask<Void, Void, Void> {
    @Override
    protected Void doInBackground(Void... params) {
        startReading(_txtArea);
        return null;
    }
}

However, you need to take steps to prevent multiple threads from accessing the EditText object at once. Otherwise you'll wind up getting a CurrentModificationException error.

http://developer.android.com/reference/android/os/AsyncTask.html