2

我有已在另一个活动中更新的项目数组列表,当我从活动返回时,我想用全新的 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
4

3 回答 3

1

所有 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

于 2018-10-23T08:11:39.177 回答
1

您只能从 UI/主线程与 UI 元素交互。

下面的代码应该在 UI 线程上发布您的操作:

fun adapterRefreshFoods(filteredList: ArrayList<Food>){
    if (!filteredList.isEmpty()){
        foodList = filteredList
        Handler(Looper.getMainLooper()).post { 
            // Code here will run in UI thread
            notifyDataSetChanged()
        }
    }
}
于 2018-10-23T08:22:37.230 回答
0

您永远不应该从主/UI 线程以外的线程访问 UI 元素。您可以使用和AsyncTask在后台加载数据并不断更新 UI 。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();
于 2018-10-23T08:35:23.553 回答