web-dev-qa-db-ja.com

ハンドラーを使用してUIスレッドに投稿する

インターネットから画像を取得してユーザーインターフェイスに表示するAndroidアプリケーションに取り組んでいます。画像を表示するためにRecyclerViewを使用しています。別のスレッドを使用して画像をダウンロードする予定です。ハンドラーを介してRecyclerViewを更新します。この概念が正しいかどうかはわかりません(AsyncTaskは知っていますが、学習目的でHandlerを実装しようとしています。)したがって、以下と同じようにコーディングしました。

_private void loadNewsThumbnailImage(ArrayList<DataItem> dataList) {
    for (DataItem item : DataList) { //DataItem is the model class
        loadThumbnailFromInternet(item);
        }
}



private void loadThumbnailFromInternet(final DataItem dataItem) {

        Thread imageDowloaderThread = new Thread(new Runnable() {
            @Override
            public void run() {
                Bitmap bitmap = null;
                try {
                    bitmap = getDataItemBitmap(dataItem.getmImageUrl());
                    dataItem.setmThumbnail(bitmap);
                    new Handler().post(new Runnable() { // Tried new Handler(Looper.myLopper()) also
                        @Override
                        public void run() {
                            mAdapter.notifyDataSetChanged();
                        }
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        imageDowloaderThread.start();

    }
_

このコードを実行しましたが、エラーが発生し、アプリケーションが終了しました。なぜこれが発生しているのかわかりません。誰かが私がそれを整理するのを手伝ってください。現在のコードの問題点を説明します。

(AsyncTaskの使用を提案しないでください(私はそれを試しましたが、正常に動作します))

[〜#〜] update [〜#〜]

取得エラー:Java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

9
droidev

UI以外のスレッドからnotifyDataSetChanged()を呼び出しているため、アプリケーションが終了します。

交換:

 new Handler().post(new Runnable() { // Tried new Handler(Looper.myLopper()) also
                        @Override
                        public void run() {
                            mAdapter.notifyDataSetChanged();
                        }
                    }); 

これとともに:

new Handler(Looper.getMainLooper()).post(new Runnable() { // Tried new Handler(Looper.myLopper()) also
                    @Override
                    public void run() {
                        mAdapter.notifyDataSetChanged();
                    }
                });
19
Sunny Shah

定義したスレッドにはルーパーとメッセージキューがないため、このスレッドでメッセージを送信することはできません。 AsyncTaskには独自のルーパーがあり、ソースコードで見つけることができます。これは、AsyncTaskで定義されているハンドラーです。

private static class InternalHandler extends Handler {
    public InternalHandler() {
        super(Looper.getMainLooper());
    }

    @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
    @Override
    public void handleMessage(Message msg) {
        AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
        switch (msg.what) {
            case MESSAGE_POST_RESULT:
                // There is only one result
                result.mTask.finish(result.mData[0]);
                break;
            case MESSAGE_POST_PROGRESS:
                result.mTask.onProgressUpdate(result.mData);
                break;
        }
    }
}
1
simonws