Android ListView обновления изображений Thumbnails с использованием AsyncTask Причины Просмотреть переработку

Я пытаюсь получить эскизы для работы с AsyncTask для файлов изображений в ListView. У меня была общая проблема Row Recycling, и, таким образом, при прокрутке эскизов присваиваются неправильные строки. Я попытался добавить теги в 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;
    }
}

Я все еще не могу понять, что еще нужно сделать, чтобы отобразить миниатюры в правильных строках WHILE SCROLLING.

Обратите внимание: после прокрутки от затронутых строк и прокрутки назад все работает нормально, но проблема с прокруткой не исчезает!

Ответ 1

От этот пост в блоге:

То, что вы хотите сделать, - это запустить каждую строчную IO или любую тяжелую перезагрузку, связанную с процессором, асинхронно в отдельном потоке. Трюк здесь заключается в том, чтобы сделать это и по-прежнему соблюдать поведение ListView в области переработки. Например, если вы запускаете AsyncTask для загрузки изображения профиля в адаптерах getView(), представление, в которое вы загружаете изображение, может быть переработано для другой позиции до завершения AsyncTask. Таким образом, вам нужен механизм, чтобы узнать, не переработано ли представление после выполнения операции async.

Один простой способ добиться этого - прикрепить некоторую часть информации к виду, которое идентифицирует, какая строка связана с ним. Затем вы можете проверить, закончилась ли целевая строка для представления, когда операция async завершается. Есть много способов добиться этого. Вот просто упрощенный набросок одного из способов сделать это:

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

Ответ 2

Использование AsyncTask.THREAD_POOL_EXECUTOR wil приводит к запуску нескольких потоков для извлечения потоков. Нет порядка в том, как они запускаются или заканчиваются и устанавливают изображение для представления. При прокрутке вперед и назад вы можете получить неправильные изображения в своих представлениях.

Я тестировал AsyncTask.THREAD_POOL_EXECUTOR, и это приводит к неправильному изображению для некоторых видов.

Ответ 3

вы можете попробовать перейти в ListView в свой конструктор Adapter из своей активности (может быть, даже в вашу задачу async зависит от того, как вы хотите ее реализовать). и сравните позицию, используя getFirstVisiblePosition() и getLastVisiblePosition() против вашего mPosition