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

これでうまくいくはずです:

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 に答える
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 に答える