使用处理程序到 Post 到 UI 线程
Use Handler To Post In To UI Thread
我正在开发一个 android 应用程序,它从 Internet 获取图像并显示在用户界面中。我正在使用 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(我试过了,效果很好))
更新
获取错误:java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
您的应用程序正在终止,因为您从非 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();
}
});
您定义的线程没有Looper,也没有消息队列,所以您不能在该线程中发送消息。 AsyncTask 有自己的 Looper,您可以在其源代码中找到它。这是 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;
}
}
}
我正在开发一个 android 应用程序,它从 Internet 获取图像并显示在用户界面中。我正在使用 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(我试过了,效果很好))
更新
获取错误:java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
您的应用程序正在终止,因为您从非 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();
}
});
您定义的线程没有Looper,也没有消息队列,所以您不能在该线程中发送消息。 AsyncTask 有自己的 Looper,您可以在其源代码中找到它。这是 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;
}
}
}