Android ListView обновление эскизов изображений с помощью AsyncTask Причины Просмотр утилизации
Я пытался получить эскизы для работы с AsyncTask для файлов изображений в ListView. У меня была общая проблема рециркуляции строк, и поэтому при прокрутке миниатюры присваиваются неправильным строкам. Я попытался добавить теги в ImageView и затем подтвердить теги в onPostExecute() в AsyncTask, но, тем не менее, безуспешно в моих попытках. Кто-нибудь, пожалуйста, помогите!
Пользовательский адаптер выглядит следующим образом:
public class MySimpleAdapter extends SimpleAdapter {
public MySimpleAdapter(Context context,
List<? extends Map<String, ?>> data, int resource,
String[] from, int[] to) {
super(context, data, resource, from, to);
// TODO Auto-generated constructor stub
}
public View getView(int position, View convertView, ViewGroup parent) {
final View v = super.getView(position, convertView, parent);
thumbnail = (ImageView) v.findViewById(R.id.thumbnail);
checker = (CheckBox) v.findViewById(R.id.checkBox);
filenametext = (TextView) v.findViewById(R.id.text1);
String pathtoimage = startLocation.concat("/"
+ filenametext.getText().toString());
desctext = (TextView) v.findViewById(R.id.text2);
String temp = desctext.getText().toString();
if (temp.equals("Directory") == true) {
checker.setEnabled(false);
switch (theme) {
case 0:
thumbnail.setImageResource(R.drawable.folder_light);
break;
case 1:
thumbnail.setImageResource(R.drawable.folder_dark);
break;
}
} else {
checker.setEnabled(true);
if (filenametext.getText().toString().endsWith(".jpg")
|| filenametext.getText().toString().endsWith(".png")
|| filenametext.getText().toString().endsWith(".bmp")) {
Boolean hashmapfound = false;
for (HashMap.Entry<String, Bitmap> entry : thumbnaillist
.entrySet()) {
String key = entry.getKey();
if (key.equals(filenametext.getText().toString())) {
Log.d(TAG, "HashMapKey Found!");
thumbnail.setImageBitmap(entry.getValue());
hashmapfound = true;
}
}
if (!hashmapfound) {
Log.d(TAG, "NO HashMapKey Found! Adding to HashMap!");
switch (theme) {
case 0:
thumbnail
.setImageResource(R.drawable.unknown_image_light);
break;
case 1:
thumbnail
.setImageResource(R.drawable.unknown_image_dark);
break;
}
thumbnail.setTag((filenametext.getText().toString()));
new GetBitMaps(thumbnail).execute(pathtoimage,
filenametext.getText().toString());
}
} else {
switch (theme) {
case 0:
thumbnail.setImageResource(R.drawable.file_light);
break;
case 1:
thumbnail.setImageResource(R.drawable.file_dark);
break;
}
}
}
return v;
}
}
AsyncTask выглядит следующим образом:
class GetBitMaps extends AsyncTask<String, Void, Bitmap> {
private ImageView thumbnail;
private String imageName;
public GetBitMaps(ImageView thumb) {
// TODO Auto-generated constructor stub
thumbnail = thumb;
}
@Override
protected Bitmap doInBackground(String... pathtoimage) {
Bitmap bmp = createThumbnail(pathtoimage[0]);
thumbnaillist.put(pathtoimage[1], bmp);
imageName = pathtoimage[1];
return bmp;
}
@Override
protected void onPostExecute(Bitmap bmp) {
if (((String) thumbnail.getTag()).equals(imageName)) {
thumbnail.setImageBitmap(bmp);
}
}
private Bitmap createThumbnail(String filepath) {
Bitmap bmp = BitmapFactory.decodeFile(filepath);
int w = bmp.getWidth();
int h = bmp.getHeight();
if (w > h) {
w = 80;
h = 40;
} else if (w < h) {
w = 40;
h = 80;
}
bmp = Bitmap.createScaledBitmap(bmp, w, h, true);
return bmp;
}
}
Я до сих пор не могу понять, что еще нужно сделать, чтобы миниатюры отображались в правильных строках во время прокрутки.
Обратите внимание: после прокрутки от затронутых строк и прокрутки назад все работает нормально, но проблема прокрутки не исчезает!
3 ответа
То, что вы хотите сделать, это запустить все операции ввода-вывода для каждой строки или любую тяжелую подпрограмму, связанную с процессором, асинхронно в отдельном потоке. Хитрость здесь заключается в том, чтобы сделать это и при этом соответствовать правилам повторного использования ListView. Например, если вы запустите AsyncTask для загрузки изображения профиля в getView() адаптера, то представление, для которого вы загружаете изображение, может быть переработано для другой позиции до того, как AsyncTask завершит работу. Итак, вам нужен механизм, чтобы узнать, не было ли представление повторно использовано после того, как вы закончили с асинхронной операцией.
Один простой способ добиться этого - прикрепить некоторую часть информации к представлению, которое идентифицирует, какая строка связана с ним. Затем вы можете проверить, является ли целевая строка для представления той же самой, когда асинхронная операция заканчивается. Есть много способов достижения этого. Вот лишь упрощенный набросок того, как вы могли бы это сделать:
public View getView(int position, View convertView,
ViewGroup parent) {
ViewHolder holder;
...
holder.position = position;
new ThumbnailTask(position, holder)
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null);
return convertView;
}
private static class ThumbnailTask extends AsyncTask {
private int mPosition;
private ViewHolder mHolder;
public ThumbnailTask(int position, ViewHolder holder) {
mPosition = position;
mHolder = holder;
}
@Override
protected Cursor doInBackground(Void... arg0) {
// Download bitmap here
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (mHolder.position == mPosition) {
mHolder.thumbnail.setImageBitmap(bitmap);
}
}
}
private static class ViewHolder {
public ImageView thumbnail;
public int position;
}
Использование AsyncTask.THREAD_POOL_EXECUTOR приведет к запуску нескольких потоков для извлечения thumnails. Там нет порядка в том, как они работают или Finisch и установить изображение для представления. При прокрутке назад и вперед вы можете получить неправильные изображения.
Я протестировал AsyncTask.THREAD_POOL_EXECUTOR, и он приводит к неправильному изображению для некоторых видов.
Вы можете попробовать передать ListView в ваш конструктор Adapter из вашей деятельности (может быть даже ваша асинхронная задача зависит от того, как вы хотите ее реализовать). и сравните положение, используя getFirstVisiblePosition() и getLastVisiblePosition() против вашего mPosition