【问题标题】:How to update ListView from AsyncTask?如何从 AsyncTask 更新 ListView?
【发布时间】:2011-11-16 15:21:12
【问题描述】:

我正在使用 AsyncTask 加载图像,而为了更新 ListView,我正在使用 notifyDataSetChanged() 方法。

notifyDataSetChanged() 不会更改 ListView onProgressUpdate() 中的任何内容。 我不想使用 cursor.requery,因为它已被弃用。

为什么 notifyDataSetChanged() 对我不起作用?

public class News extends BasicActivity implements OnItemClickListener{
private SQLiteDatabase db = null;
private ListView lvNews;
private TaskImgSm taskImgSm = null;
private NewsListAdapter adapter;
private Cursor cur;
boolean pause = false;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.news);

    db = SQLiteDatabase.openDatabase(((MyApp) getApplication()).getDbPath(), null, SQLiteDatabase.OPEN_READWRITE);
    lvNews = (ListView) findViewById(R.id.list_news);
    lvNews.setOnItemClickListener(this);
    listFilling();

    if (taskImgSm != null && taskImgSm.getStatus() != AsyncTask.Status.FINISHED) taskImgSm.cancel(true);
    taskImgSm = new TaskImgSm();
    taskImgSm.execute();        
}

private void listFilling() {
    cur = db.query("news", new String[] { "_id", "id_news", "title", "date", "img_url", "img_sm" }, null, null, null, null, null);
    startManagingCursor(cur);
    adapter = new NewsListAdapter(this, cur, db);
    lvNews.setAdapter(adapter);
    adapter.notifyDataSetChanged();
}

class TaskImgSm extends AsyncTask<Void, String, Void> {
    Cursor curs;
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        curs = db.query("news", new String[] { "_id", "id_news", "img_url", "img_sm" }, null, null, null, null, null);
        startManagingCursor(curs);
    }

    @Override
    protected Void doInBackground(Void... unused) {
        curs.moveToFirst();
        while (curs.isAfterLast() == false) {
            if (curs.getBlob(curs.getColumnIndex("img_sm")) == null) {
                String imgUrl = curs.getString(curs.getColumnIndex("img_url"));
                String idNews = curs.getString(curs.getColumnIndex("id_news"));
                updateImg(imgUrl, idNews, "img_sm");
                publishProgress();
            }
            curs.moveToNext();
        }           
        return (null);
    }

    private void updateImg(String img_URL, String whereId, String imgColumn) {
        try {
            DefaultHttpClient mHttpClient = new DefaultHttpClient();
            HttpGet mHttpGet = new HttpGet();
            mHttpGet.setURI(new URI(img_URL));
            HttpResponse mHttpResponse = mHttpClient.execute(mHttpGet);
            if (mHttpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                HttpEntity entity = mHttpResponse.getEntity();
                if (entity != null) {
                    // insert to database
                    ContentValues values = new ContentValues();
                    values.put(imgColumn, EntityUtils.toByteArray(entity));
                    db.update("news", values, "id_news=" + whereId, null);
                }
            }
        } catch (URISyntaxException e) {e.printStackTrace();
        } catch (ClientProtocolException e) {e.printStackTrace();
        } catch (IOException e) {e.printStackTrace();}
    }

    @Override
    protected void onProgressUpdate(String... item) {
        if (pause == false) {
            adapter.notifyDataSetChanged();
        }
    }

    @Override
    protected void onPostExecute(Void unused) {}
}

@Override
protected void onPause() {
    pause = true;
    super.onPause();
}

@Override
protected void onResume() {
    pause = false;
    adapter.notifyDataSetChanged();
    super.onResume();
}

@Override
protected void onDestroy() {
    if (taskImgSm != null && taskImgSm.getStatus() != AsyncTask.Status.FINISHED) taskImgSm.cancel(true);
    super.onDestroy();
}
}

【问题讨论】:

  • 1.不要将图像存储在 DB 2 中。使用 Ihttp://stackoverflow.com/questions/541966/android-how-do-i-do-a-lazy-load-of-images-in-listview/3068012#3068012
  • 为什么不能用DB来存储图片?据我所知,与文件系统相比,它的工作速度足够快。
  • 您的数据库将变得不必要......在这种情况下,Android 上的良好做法是只存储一个路径(在 android 文件系统(缓存/外部/内部存储)上)以在 db 中归档......无论如何...您的数据库是静态的(与 apk 一起分发)还是您下载它?
  • 你为什么不把图片放到drawable文件夹中并使用重写的SimpleCursorAdapter方法@Override public void setViewImage(ImageView v, String value) { Context ctx = v.getContext(); v.setImageResource(ctx .getResources().getIdentifier(value, "drawable", ctx .getPackageName())); }和在db中只存储这个drawable的名称?
  • 图片存放在文件夹/db/sd/drawable中是没有问题的。之后我只想更新 ListView

标签: android database listview android-asynctask


【解决方案1】:

它不起作用的原因是因为notifyDataSetChanged() 只告诉ListView 适配器中的数据 发生了变化。由于该数据没有更改(因为您没有再次查询数据库),因此 ListView 不会显示任何更新。您需要再次执行查询并更新适配器中的数据,然后调用notifyDatasetChanged()

【讨论】:

  • “更新适配器中的数据”是什么意思?我必须在 onProgressUpdate 方法中写什么?
【解决方案2】:

为什么不使用 ContentProvider。

使用 ContentProvider,您可以使用 notifyChange(uri) 方法更新表格

这里的教程http://thinkandroid.wordpress.com/2010/01/13/writing-your-own-contentprovider/

【讨论】:

    【解决方案3】:

    我认为您可能希望在onPostExecute() 方法中更新ListView 中的ImageView。这就是我完成与您所做的类似的事情的方式:Multithreading For Performance

    【讨论】:

      猜你喜欢
      • 2017-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-15
      • 1970-01-01
      • 2020-03-20
      相关资源
      最近更新 更多