简体   繁体   English

如何异步设置recyclerView适配器

[英]How to Set recyclerView adapter asynchronously

I've written a class which looks for specific files in a folder and save their address (plus 3 other attributes) to shared preferences then in my custom adapter i make a call to a method (the method (which is named getAllItems ) reads the data from shared preferences, instantiate new custom objects and add them to a list and returns the list. This is the part that the biggest loading happen) then the adapter uses that list of items to retrieve the address from every single item, generate a Bitmap and show them in a recyclerView this is the error i'm getting: 我编写了一个类,用于在文件夹中查找特定文件,并将其地址(加上3个其他属性)保存为共享首选项,然后在我的自定义适配器中调用方法(该方法(名为getAllItems )读取共享的首选项中的数据,实例化新的自定义对象,并将它们添加到列表中并返回列表。这是发生最大负载的部分),然后适配器使用该项目列表从每个项目中检索地址,生成位图并在recyclerView中显示它们,这是我得到的错误:

 E/AndroidRuntime: FATAL EXCEPTION: pool-1-thread-1
        Process: com.amir.example, PID: 4968
        java.util.ConcurrentModificationException
            at java.util.HashMap$HashIterator.nextEntry(HashMap.java:787)
            at java.util.HashMap$KeyIterator.next(HashMap.java:814)
            at com.android.internal.util.XmlUtils.writeSetXml(XmlUtils.java:355)
            at com.android.internal.util.XmlUtils.writeValueXml(XmlUtils.java:693)
            at com.android.internal.util.XmlUtils.writeMapXml(XmlUtils.java:300)
            at com.android.internal.util.XmlUtils.writeMapXml(XmlUtils.java:269)
            at com.android.internal.util.XmlUtils.writeMapXml(XmlUtils.java:235)
            at com.android.internal.util.XmlUtils.writeMapXml(XmlUtils.java:192)
            at android.app.SharedPreferencesImpl.writeToFile(SharedPreferencesImpl.java:600)
            at android.app.SharedPreferencesImpl.-wrap2(SharedPreferencesImpl.java)
            at android.app.SharedPreferencesImpl$2.run(SharedPreferencesImpl.java:515)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
            at java.lang.Thread.run(Thread.java:818)

now when the number of files are few (like 20 match out of 100 files) the app works fine but when there are too many (like 200 items out of 8000 files) the app crashes 现在,当文件数很少时(例如100个文件中有20个匹配),应用程序可以正常工作,但是当文件太多(例如8000个文件中的200个项目)时,应用程序崩溃

I've tried to load the items into adapter asynchronously: this is in MainActivity.java 我尝试将项目异步加载到适配器中:这在MainActivity.java中

 public class AsyncAdapter extends AsyncTask<Void, Void, Void> {
    @Override
    protected Void doInBackground(Void... params) {

        //This line will load the files into shared preferences (DataSource is my sharedPreferences)
        Loader.loadPhoneStickers(adapter.getDataSource()); 

        //this will cause the list that the adapter is attached to, to get updated and load all the items that were added to shared preferences 
        //this method will make a call to getAllItems and notifyItemRangeChanged
        adapter.refresh();
        return null;
    }
}

but the error remains the same whether i do the set the adapter asynchronously (setting the adapter would cause the all the loading to take place)or synchronously 但是无论我异步设置适配器(设置适配器将导致所有加载发生)还是同步,错误仍然相同

where should i do the loading? 我应该在哪里装载? will otto be of any helps? 奥托会有什么帮助吗?

You will need to override this method inside asynctask and to that on postexecute which runs on ui thread. 您将需要在asynctask内以及在ui线程上运行的postexecute上覆盖此方法。 You cannot refresh adapter from ui Thread. 您无法从ui Thread刷新适配器。

 public class AsyncAdapter extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {

    //This line will load the files into shared preferences (DataSource is my sharedPreferences)
    Loader.loadPhoneStickers(adapter.getDataSource()); 

    //this will cause the list that the adapter is attached to, to get updated and load all the items that were added to shared preferences 
    //this method will make a call to getAllItems and notifyItemRangeChanged
    return null;
    }

 @Override
 protected void onPostExecute(Void aVoid) {
    super.onPostExecute(aVoid);

      adapter.refresh();
  }
}

Generally when you work in different thread you cannot interact with ui elements. 通常,当您在其他线程中工作时,无法与ui元素进行交互。 Common practice is to use postExecute in Asynctask.Post execute is called immediately after doInbackground is finished and is called on UI thread where you can do all your Ui related stuff. 通常的做法是在Asynctask中使用postExecute。doInbackground完成后立即调用post execute,并在UI线程上调用它,您可以在其中执行所有与Ui相关的工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM