notifyDataSetChanged没有刷新listview

时间:2013-05-25 10:40:10

标签: android asynchronous android-listview notifydatasetchanged

最初我从服务器获取数据列表并将其设置为listview。

当向下滚动列表视图时,我从服务器收集数据并调用我的自定义适配器的notifydatasetchanged。

在自定义适配器的getView()方法中,我通过asyntask从服务器下载图像。成功下载并在本地存储后。然后只是尝试刷新该asyntask的onPostExecute列表视图。但它没有得到更新。

onPostExecute上的日志正在打印,但listview没有得到刷新。

public void loadBitmap(MainActivity mainActivity,String imageKey,ImageView imageView,boolean isScrolling) {         final Bitmap bitmap = getBitmapFromCache(imageKey);

    if (bitmap != null) {
        imageView.setImageBitmap(bitmap);
    } else {
        imageView.setImageResource(R.drawable.ic_launcher);
        if (!isScrolling && !mCurrentTasks.contains(imageKey)
                && mainActivity.internetIsAvailable()) {
            BitmapLoaderTask task = new BitmapLoaderTask(imageKey,
                    mainActivity.getAdapter());
            task.execute();
        }
    }
}

private class BitmapLoaderTask extends AsyncTask<Void, Void, Bitmap> {
    private ListAdapter mListAdapter;
    private String mImageKey;

    public BitmapLoaderTask(String imageKey, ListAdapter adapter) {
        mListAdapter = adapter;
        mImageKey = imageKey;
    }

    @Override
    protected void onPreExecute() {
        mCurrentTasks.add(mImageKey);
    }

    @Override
    protected Bitmap doInBackground(Void... params) {
        Bitmap b = null;
        try {
            URL url = new URL(mImageKey);
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection();
            connection.connect();
            b = BitmapFactory.decodeStream(connection.getInputStream());

            if (b != null) {
                int width = b.getWidth();
                int height = b.getHeight();

                if (width >= mMaxWidth || height >= mMaxHeight) {
                    while (true) {
                        if (width <= mMaxWidth || height <= mMaxHeight) {
                            break;
                        }
                        width /= 2;
                        height /= 2;
                    }
                    b = Bitmap.createScaledBitmap(b, width, height, false);
                }

                connection.disconnect();
                addBitmapToCache(mImageKey, b);
                return b;
            }
            return null;
        } catch (IOException e) {
            if (e != null) {
                e.printStackTrace();
            }
            return null;
        }
    }

    @Override
    protected void onPostExecute(Bitmap param) {
        mCurrentTasks.remove(mImageKey);
        if (param != null) {
            mListAdapter.notifyDataSetChanged();
        }
    }
}

2 个答案:

答案 0 :(得分:0)

你的代码看起来正确..但我认为问题可能是mainActivity.getAdapter()我认为你应该在全局范围内声明适配器。

private AdapterYourCustomAdapter adapter;

然后在onCreate()

adapter = new AdapterYourCustomAdapter(context,arraylist(whatever constructor is));

然后将调用传递给它:

if (bitmap != null) {
        imageView.setImageBitmap(bitmap);
    } else {
        imageView.setImageResource(R.drawable.ic_launcher);
        if (!isScrolling && !mCurrentTasks.contains(imageKey)
                && mainActivity.internetIsAvailable()) {
            new BitmapLoaderTask( imageKey, adapter ).execute();
        }
    }

答案 1 :(得分:0)

尝试将每个位图的ImageView传递给构造中的BitmapLoaderTask,并将ImageView作为成员变量保留在其中。加载完位图后,使用onPostExecute方法将该位图指定为ImageView drawable。

private class BitmapLoaderTask extends AsyncTask<Void, Void, Bitmap> {

  private String mImageKey;
  private ImageView mImageView;

  public BitmapLoaderTask(ImageView imageView, String imageKey) {
    mImageView = imageView;
    mImageKey = imageKey;
  }

  protected void onPreExecute() {

    /* Pre execute stuff */

  }

  protected Bitmap doInBackground(Void... params) {

    /* Your bitmap processing */

    return bitmap;
  }

  protected void onPostExecute(Bitmap param) {
    if(param != null) {
      mImageView.setImageBitmap(param);
    }
  }
}

这是构建AsyncTask的完美示例。 doInBackground()方法在后台线程上运行,因此不会干扰UI处理,但是android权限要求不允许此类后台线程触及UI元素。这就是onProgressUpdate()onPostExecute()的用途,只要doInBackground达到了更新的里程碑,它们就会在主UI线程上运行快速UI更新。在这种情况下,您可以使用它们在相应的位图准备就绪时通知您的ImageView对象。