I have a custom SimpleCursorAdapter with a getView like this:
public View getView(int position, View convertView, ViewGroup parent) {
//this.changeCursor(c); tried this didn't work.
this.c.moveToPosition(position);
int urlCol = c.getColumnIndex("url");
final String url = c.getString(urlCol);
//other code stuff.
imageDownloader.download(url, thumbnail, rowId, db,pb);
The imageDownloader calls an update on the DBAdapter but the c.getString(urlCol) still gives me the previous value. I tried putting changeCursor at the position above but I still got the same value. Where exactly should I be calling 开发者_开发百科this? Thanks!
I actually don't want the ListVIew to redraw I just want to get the latest data into the cursor. I'm passing in my imageview and url into the ImageDownloader class to download the image, set the bitmap to the imageview and update the database. I noticed the cursor was not updated as the getView method returns me the same data.
This is my custom simplecursoradapter declaration. getview is mentioned above.
public class MessagesCursorAdapter extends SimpleCursorAdapter {
private final ImageDownloader imageDownloader = new ImageDownloader();
ImageDownloader class
public void download(String url, ImageView imageView, int rowId,
TestDbAdapter db,ProgressBar pb) {
//url can be a http:// or /mnt/sdcard/mnt/ etc etc
//some lenghty code to check if it exists physically on the phone. else....
forceDownload(url, imageView, rowId, db,pb);
private void forceDownload(String url, ImageView imageView, int rowId,
TestDbAdapter db,ProgressBar pb) {
BitmapDownloaderTask task = new BitmapDownloaderTask(imageView, rowId,
db,pb);
AsyncTask class in the ImageDownloader class
class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
private String url;
private int rowId;
private TestDbAdapter db;
private ProgressBar pb;
private final WeakReference<ImageView> imageViewReference;
public BitmapDownloaderTask(ImageView imageView, int rowId,
TestDbAdapter db,ProgressBar pb) {
imageViewReference = new WeakReference<ImageView>(imageView);
this.rowId = rowId;
this.db = db;
this.pb = pb;
}
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
pb.setVisibility(View.VISIBLE);
}
@Override
protected Bitmap doInBackground(String... params) {
url = params[0];
return downloadBitmap(url);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
}
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
if ((this == bitmapDownloaderTask)) {
int pos = url.lastIndexOf("/");
String fileName = url.substring(pos, url.length());
System.out.println(fileName);
String extLoc = Environment.getExternalStorageDirectory()
+ "/Test";
File folder = new File(extLoc);
if (!folder.exists()) {
folder.mkdir();
}
try {
FileOutputStream out = new FileOutputStream(extLoc
+ fileName);
boolean result = db.updateMessageUrl(rowId, extLoc + fileName);
//should update cursor here, purpose is to change the url link to a physical location on the phone.
bitmap.compress(Bitmap.CompressFormat.JPEG, 95, out);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inTempStorage = new byte[24 * 1024];
options.inJustDecodeBounds = false;
options.inSampleSize = 2;
Bitmap thumbnail = BitmapFactory.decodeFile(extLoc
+ fileName, options);
imageView.setImageBitmap(bitmap);
addBitmapToCache(url, bitmap);
pb.setVisibility(View.GONE);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Ok if it looks weird, I'm just hiding some names.
First do:
c.moveToFirst();
before access ANY data then do the rest you want. In your case call c.moveToFirst()
, not in getView()
but outside, since you'll get all the same, because getView() is called multiple times when it performs the populating. Perhaps, call it in the method where you are returning the cursor.
When you do the accessing, dont forget to move the cursor for the next data c.moveToNext();
you MUST do this inside getView();
I don't have a good answer that will work with the way your CursorAdapter is setup.
You should only run AsyncTask once from the ListActivity. Maybe have the AsyncTask download all images in the database which are pending download and update the database? You can use onProgressUpdate to call a method in ListActivity to do the notifyDataSetchanged().
What you want is notifyDataSetChanged() and notifyDataSetInvalidated(). Your asyncTask onPostExecute method should return a new/updated cursor to the ListActivity then from the ListActivity call notifyDataSetchanged() and notifyDataSetInvalidated.
Edit: Same question as this.
精彩评论