【问题标题】:Simple fix for scrolling when custom adapter is changing?自定义适配器更改时滚动的简单修复?
【发布时间】:2014-04-15 10:34:26
【问题描述】:

使用我的自定义适配器 - 我正在使用 AsyncTask 填充 listiewdoInBackground 更新用于自定义适配器的 ArrayLists。 onProgressUpdate 调用adapter.notifyDataSetChanged();

加载大量文件时,我希望 UI 能够响应,但是当您尝试在列表仍在填充时滚动时,我收到此错误:

 java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes.


@Override
        protected Boolean doInBackground(DbxFileSystem... params) {
            //Opens thumbnails for each image contained in the dropbox folder
            try {
                DbxFileSystem fileSystem = params[0];
                numFiles = fileSystem.listFolder(currentPath).size();
                for (DbxFileInfo fileInfo: fileSystem.listFolder(currentPath)) {
                    String filename = fileInfo.path.getName();


                    try{
                        if(!fileInfo.isFolder)
                        {
                            Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
                            pix.add(image);
                            paths.add(fileInfo.path);
                            publishProgress(1); //use this to update the ListView
                        }
                        else
                        {
                            //must be a folder if it has no thumb, so add folder icon
                            Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.dbfolder);
                            pix.add(image);
                            paths.add(fileInfo.path);
                            publishProgress(1);


                        }

                    catch(Exception e)
                    {
                        e.printStackTrace();
                    }
                    System.gc();
                }

            }
            catch (Exception e) {
                e.printStackTrace();
                return false;
            } finally {
            }
            return true;
        }

       @Override
        protected void onProgressUpdate(Integer...progress) {

           if(pix.size()==1) // //not ideal but works for now, only bind the adapter if its the first time we have looped through.
           {
           adapter = new ImageAdapter(getApplicationContext(), pix, paths, numFiles);
           lstView.setAdapter(adapter);
           }

           adapter.notifyDataSetChanged();
           lstView.requestLayout();
           super.onProgressUpdate(progress);
        }

谁能看出这里有什么问题?我能做些什么来防止它? 我最初使用的是进度条,只有在它们全部加载后才显示填充内容,但我更愿意显示增量加载并让用户在加载内容时滚动。

附言我认为这是一个很常见的问题,并且已经阅读了几个类似的问题,但我仍然无法弄清楚我需要更改什么。

【问题讨论】:

    标签: android android-listview arraylist android-asynctask


    【解决方案1】:

    您的适配器将 pix、numFiles 和路径作为数据源,并且由于您在 doInBackground() 中修改这些集合,该集合在 在非 UI 线程上运行,您会得到这个例外。

    new ImageAdapter(getApplicationContext(), pix, paths, numFiles); 通过 reference 传递这些集合。

    【讨论】:

    • 谢谢,我会试试这个 - 这是否意味着更新适配器时列表会自动跳回顶部?
    • 所以在我的 onProgressUpdate 中我应该只有: adapter = new ImageAdapter(getApplicationContext(), pix, paths, numFiles); lstView.setAdapter(适配器);
    • 不,问题是您正在将项目添加到线程中的像素和路径集合中。在 onProgressUpdate 中创建适配器不会改变您从非 UI 线程修改适配器数据的事实。你不能这样做。您应该等到 doinBackground 完成并在 onPostExecute() 中填写您的适配器,然后调用 notifyDatasetChanged()。这就是 asyncTask 的使用方式。
    • 所以我必须等到整个 AsyncTask 完成后才能显示我的列表?有没有办法在它们到达时一一显示?最好让用户看到项目正在加载,而不是让“请稍候”对话框等待几秒钟。
    • 有办法做到这一点。但是 AsyncTask 可能不是最好的解决方案,因为 onProgressUpdate 不打算这样做。
    猜你喜欢
    • 1970-01-01
    • 2020-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多