Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Handler To Post In To UI Thread

I am working on an android application, that fetches image from Internet and show in the user interface. I am using RecyclerView for showing the image. I am planning to download the image using a separate thread. and update RecyclerView via the handler. I dont know wether this concept is correct or not, (I know AsyncTask, but for learning purpose I am trying to implement Handler.) So I coded for the same as below

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();

    }

I have executed this code but I am getting error, and application is terminated, I don't know why this is happening . please any one help me to sort it out. and explain what is the problem for the current code.

(Please do not suggest to use AsyncTask (I have tried that and it works fine))

UPDATE

Error getting :java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

like image 966
droidev Avatar asked Aug 05 '15 06:08

droidev


2 Answers

Your application is getting terminated because you are calling notifyDataSetChanged() from a non UI Thread.

Replace:

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

With this:

new Handler(Looper.getMainLooper()).post(new Runnable() { // Tried new Handler(Looper.myLopper()) also
                    @Override
                    public void run() {
                        mAdapter.notifyDataSetChanged();
                    }
                });
like image 157
Sunny Shah Avatar answered Sep 30 '22 17:09

Sunny Shah


The thread you defined does not have a Looper, and no message queue,so you can not send message in this thread. AsyncTask has its own Looper which you can find it in its source code. This is handler defined in 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;
        }
    }
}
like image 44
simonws Avatar answered Sep 30 '22 18:09

simonws