如何从AsyncTask更新ListView?

发布于 2024-12-16 21:18:22 字数 3901 浏览 0 评论 0原文

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

但是 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();
}
}

I am loading images by using AsyncTask and for updating ListView I am using notifyDataSetChanged() method.

But notifyDataSetChanged() doesn't change anything in the ListView onProgressUpdate().
I don't want to use cursor.requery because it is deprecated method.

Why notifyDataSetChanged() is not working for me?

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();
}
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

淡写薰衣草的香 2024-12-23 21:18:22

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

The reason it's not working is because notifyDataSetChanged() only tells the ListView that the data in the adapter has changed. Since that data hasn't changed (because you haven't queried the database again), then the ListView won't show any updates. You need to execute the query again and update the data in the adapter, then call notifyDatasetChanged().

故人的歌 2024-12-23 21:18:22

为什么不使用 ContentProvider。

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

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

Why don't use a ContentProvider.

With a ContentProvider you can update your table with the notifyChange(uri) method

Tutorial for that here http://thinkandroid.wordpress.com/2010/01/13/writing-your-own-contentprovider/

┈┾☆殇 2024-12-23 21:18:22

我想您可能想在 onPostExecute() 方法中更新 ListView 中的 ImageView 。这就是我完成与您正在做的类似的事情的方法: Multithreading For性能

I think you may want to update the ImageView in a ListView in the onPostExecute() method. This is how I accomplished something similar to what you are doing : Multithreading For Performance

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文