0

如果 TextView.setText 在 Thread 内,我的应用程序会崩溃:
注意:以下类在 MainActivity 内。

private class StreamThread extends Thread {
    public StreamThread() {

    }

    public void run() {
        byte[] buffer = new byte[1024];
        int bytes;
        while (true) {
            try {
                bytes = mmInStream.read(buffer);
                String message = new String(buffer, 0, bytes);
                //THIS IS IMPORTANT, READ THIS PLEASE
                //I tested many times my app to find the problem, and I found, my app crashes when TextView.setText() is executed

                //Here starts the problem
                ((TextView) findViewById(R.id.textView)).setText(message);
            } catch (IOException e) {
                break;
            }
    }

}
4

3 回答 3

0

线程被设计为通过分开允许另一个代码同时执行来执行代码。不幸的是线程与 UI 不兼容,但我有一个解决方案。

runOnUiThread(new Runnable() {
    @Override
    public void run () {
        //Some stuff that needs to interact with the user (UI).
    }
}
于 2015-06-16T23:47:51.570 回答
0

您必须在 ui 线程中更新可视化组件。出于您的目的,您应该使用在 ui 线程中运行的 AsyncTask、Service 或 Runnable。

例如,您在以下代码中使用AsyncTask :

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView textview = (TextView) findViewById(R.id.textView);
        new StreamAsyncTask(textview).execute();
    }

    private class StreamAsyncTask extends AsyncTask<Void, String, Void> {

        private TextView textview;

        public StreamAsyncTask(TextView textview) {
            this.textview = textview;
        }

        @Override
        protected Void doInBackground(Void... voids) {
            byte[] buffer = new byte[1024];
            int bytes;
            while (true) {
                try {
                    bytes = mmInStream.read(buffer);
                    String message = new String(buffer, 0, bytes);
                    publishProgress(message);
                } catch (IOException e) {
                    break;
                }
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);
            textview.setText(values[0]);
        }
    }
}

或者您可以使用 Activity 的方法runOnUiThread

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        ((TextView) findViewById(R.id.textView)).setText(message);
    }
});

最后一种方式更容易理解,但第一种方式更灵活。阅读 AsyncTasks:http: //developer.android.com/reference/android/os/AsyncTask.html

于 2015-06-16T23:48:38.097 回答
0

这应该可以解决问题:

private class StreamThread extends Thread {
    public StreamThread() {}

    public void run() {
        byte[] buffer = new byte[1024];
        int bytes;
        while (true) {
            try {
                bytes = mmInStream.read(buffer);
                String message = new String(buffer, 0, bytes);

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ((TextView) findViewById(R.id.textView)).setText(message);
                    }
                });
            } catch (IOException e) {
                break;
            }
        }
    }
}

苏,怎么了?Android 的 UI 是单线程的。这意味着您不允许从 ui 线程以外的另一个线程更改 ui。您可以使用runOnUiThread -Method或使用Handler将更改发布到 ui 线程。

于 2015-06-16T23:49:54.260 回答