从另一个线程刷新 RecyclerView 导致错误
Refreshing RecyclerView from another thread causing error
我有项目数组列表已在另一个 activity 中更新,因为我 return 来自 activity,我想用全新的 ArrayList() 刷新我的 recyclerview。为了避免滞后,我将此刷新放在其他可运行线程上,并将 ProgressBar 而不是 RecyclerView。
在新线程中,此方法在适配器内部调用 (recyclerViewAdapter.adapterRefreshFoods()
)
fun adapterRefreshFoods(filteredList: ArrayList<Food>){
if (!filteredList.isEmpty()){
foodList = filteredList
notifyDataSetChanged()
}
}
这导致以下异常。 (当我在 UIThread 中刷新它时它工作正常)
java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling android.support.v7.widget.RecyclerView
所有 UI 组件只能通过主线程访问,因为 UI 元素不是线程安全的,主线程是它的所有者。
mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message inputMessage) {
//Call your UI related method
}
}
参考:https://developer.android.com/training/multiple-threads/communicate-ui#java
您只能从 UI/Main 线程与 UI 元素交互。
下面的代码应该 post 您在 UI 线程上的操作:
fun adapterRefreshFoods(filteredList: ArrayList<Food>){
if (!filteredList.isEmpty()){
foodList = filteredList
Handler(Looper.getMainLooper()).post {
// Code here will run in UI thread
notifyDataSetChanged()
}
}
}
您永远不应该从 main/UI 线程以外的线程访问 UI 元素。您可以使用 AsyncTask
在后台加载数据并使用 publishProgress()
和 onProgressUpdate()
.
连续更新 UI
new AsyncTask<Void, List<YourDataClass>, List<YourDataClass>>(){
@Override
protected List<YourDataClass> doInBackground(Void... voids) {
// Fetch data here and call publishProgress() to invoke
// onProgressUpdate() on the UI thread.
publishProgress(dataList);
return dataList;
}
@Override
protected void onProgressUpdate(List<YourDataClass>... values) {
// This is called on the UI thread when you call
// publishProgress() from doInBackground()
}
@Override
protected void onPostExecute(List<YourDataClass> dataList) {
// This is called on the UI thread when doInBackground() returns, with
// the result as the parameter
}
}.execute();
我有项目数组列表已在另一个 activity 中更新,因为我 return 来自 activity,我想用全新的 ArrayList() 刷新我的 recyclerview。为了避免滞后,我将此刷新放在其他可运行线程上,并将 ProgressBar 而不是 RecyclerView。
在新线程中,此方法在适配器内部调用 (recyclerViewAdapter.adapterRefreshFoods()
)
fun adapterRefreshFoods(filteredList: ArrayList<Food>){
if (!filteredList.isEmpty()){
foodList = filteredList
notifyDataSetChanged()
}
}
这导致以下异常。 (当我在 UIThread 中刷新它时它工作正常)
java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling android.support.v7.widget.RecyclerView
所有 UI 组件只能通过主线程访问,因为 UI 元素不是线程安全的,主线程是它的所有者。
mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message inputMessage) {
//Call your UI related method
}
}
参考:https://developer.android.com/training/multiple-threads/communicate-ui#java
您只能从 UI/Main 线程与 UI 元素交互。
下面的代码应该 post 您在 UI 线程上的操作:
fun adapterRefreshFoods(filteredList: ArrayList<Food>){
if (!filteredList.isEmpty()){
foodList = filteredList
Handler(Looper.getMainLooper()).post {
// Code here will run in UI thread
notifyDataSetChanged()
}
}
}
您永远不应该从 main/UI 线程以外的线程访问 UI 元素。您可以使用 AsyncTask
在后台加载数据并使用 publishProgress()
和 onProgressUpdate()
.
new AsyncTask<Void, List<YourDataClass>, List<YourDataClass>>(){
@Override
protected List<YourDataClass> doInBackground(Void... voids) {
// Fetch data here and call publishProgress() to invoke
// onProgressUpdate() on the UI thread.
publishProgress(dataList);
return dataList;
}
@Override
protected void onProgressUpdate(List<YourDataClass>... values) {
// This is called on the UI thread when you call
// publishProgress() from doInBackground()
}
@Override
protected void onPostExecute(List<YourDataClass> dataList) {
// This is called on the UI thread when doInBackground() returns, with
// the result as the parameter
}
}.execute();