Intereting Posts
OkHttp Library – NetworkOnMainThreadException для простой публикации Размер файла, который мы получаем через функцию AssetManager getAssets в Android Новый список приложений в стиле «Входящие» для Android с прорисовкой влево и вправо Является ли поток экземпляра базы данных Sqlite безопасным Я получаю «Ошибка: не найден ресурс, который соответствует указанному имени (при значении со значением @ integer / google_play_services_version)» Настройка JAVA_HOME для intelliJ? Изменение динамической ширины и высоты размещения Почему важно устанавливать полезную нагрузку разработчика с помощью биллинга в приложении? Не удается получить панель действий в классе фрагментов Реалии использования QT C ++ для написания приложения для кросс-платформенных телефонов Как избежать отклонения моего диалога прогресса, когда пользователь касается экрана? Изменение изображения и сохранение изображений EXIF ​​(ориентация, поворот и т. Д.) Использует ли ProGuard проблему? Конверсия в формат Dalvik завершилась с ошибкой 1 Решение? Получение UnknownLengthHttpInputStream при получении InputStream из HttpURLConnection в android

Использование AsyncTask для загрузки изображений в ListView

У меня есть один ListView, который может содержать изображение. Это зависит от того, существует ли изображение в SDCARD.

Вот мой пример кода:

public class MainActivity extends Activity { ListView mListView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mListView = new ListView(this); setContentView(mListView); String[] arr = new String[] { "/example/images/1.jpg", "/example/images/2.jpg", "/example/images/3.jpg", "/example/images/4.jpg", "/example/images/5.jpg", "/example/images/6.jpg", "/example/images/7.jpg", "/example/images/8.jpg", "/example/images/9.jpg", "/example/images/1.jpg", "/example/images/2.jpg", "/example/images/3.jpg", "/example/images/4.jpg", "/example/images/5.jpg", "/example/images/6.jpg", "/example/images/7.jpg", "/example/images/8.jpg", "/example/images/9.jpg", "/example/images/1.jpg", "/example/images/2.jpg", "/example/images/3.jpg", "/example/images/4.jpg", "/example/images/5.jpg", "/example/images/6.jpg", "/example/images/7.jpg", "/example/images/8.jpg", "/example/images/9.jpg", "/example/images/1.jpg", "/example/images/2.jpg", "/example/images/3.jpg", "/example/images/4.jpg", "/example/images/5.jpg", "/example/images/6.jpg", "/example/images/7.jpg", "/example/images/8.jpg", "/example/images/9.jpg"}; List<String> list = Arrays.asList(arr); MyAdapter adapter = new MyAdapter(this, R.layout.listitem_imv, list); mListView.setAdapter(adapter); } class MyAdapter extends ArrayAdapter<String>{ List<String> mList; LayoutInflater mInflater; int mResource; public MyAdapter(Context context, int resource, List<String> objects) { super(context, resource, objects); mResource = resource; mInflater = getLayoutInflater(); mList = objects; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view; if(convertView == null){ view = mInflater.inflate(mResource, null); }else{ view = convertView; } ImageView imageView = (ImageView) view.findViewById(R.id.imv); TextView textView = (TextView) view.findViewById(R.id.txv); imageView.setTag(mList.get(position));//tag of imageView == path to image new LoadImage().execute(imageView); textView.setText(mList.get(position).toString()); return view; } } class LoadImage extends AsyncTask<Object, Void, Bitmap>{ private ImageView imv; private String path; @Override protected Bitmap doInBackground(Object... params) { imv = (ImageView) params[0]; path = imv.getTag().toString(); Bitmap bitmap = null; File file = new File( Environment.getExternalStorageDirectory().getAbsolutePath() + path); if(file.exists()){ bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); } return bitmap; } @Override protected void onPostExecute(Bitmap result) { if(result != null && imv != null){ imv.setVisibility(View.VISIBLE); imv.setImageBitmap(result); }else{ imv.setVisibility(View.GONE); } } } } 

Каталог 'sdcard / example / images' имеет изображения: 1.jpg, 2.jpg, 3.jpg, 4.jpg, 6.jpg, 7.jpg и 9.jpg. Ожидаемый результат: пример

Но, если я быстро прокручу список, некоторые изображения вставляются в неправильные элементы. Это происходит из-за использования метода convertView в методе getView ().

Если я использую следующий код, код работает нормально:

  //if(convertView == null){ // view = mInflater.inflate(mResource, null); //}else{ // view = convertView; //} view = mInflater.inflate(mResource, null); 

Когда список прокручивается быстро, две asyncTasks могут ссылаться на один вид View из-за использования convertView. Как я могу отменить AsyncTask, когда вид больше не виден? (И является useb другим элементом ListView)

редактировать

  @Override protected void onPostExecute(Bitmap result) { if(result != null && imv != null){ if(imv.getTag().equals(path)){ imv.setVisibility(View.VISIBLE); imv.setImageBitmap(result); }else{ imv.setVisibility(View.GONE); } }else{ imv.setVisibility(View.GONE); } } 

Solutions Collecting From Web of "Использование AsyncTask для загрузки изображений в ListView"

Вы можете отправить ImageView в конструктор задачи и сохранить ссылку на путь изображения там. Теперь в onPostExecute проверьте, совпадает ли текущий тег ImageView с тем, с которого вы начали работать. Если да, то установите изображение. Если нет, ничего не делайте.

Однако это означает, что изображение будет загружено в любом случае. Вы просто не установите неправильное изображение в представлении.

EDIT: сначала передайте ImageView в конструктор задачи:

 new LoadImage(imageView).execute() 

Затем сохраните ссылку на ImageView и путь изображения в конструкторе LoadImage. Важно сохранить путь в конструкторе, а не в doInBackground, чтобы убедиться, что мы не сталкиваемся с проблемами с несколькими потоками. Затем в onPostExecute мы проверяем текущий путь.

 class LoadImage extends AsyncTask<Object, Void, Bitmap>{ private ImageView imv; private String path; public LoadImage(ImageView imv) { this.imv = imv; this.path = imv.getTag().toString(); } @Override protected Bitmap doInBackground(Object... params) { Bitmap bitmap = null; File file = new File( Environment.getExternalStorageDirectory().getAbsolutePath() + path); if(file.exists()){ bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); } return bitmap; } @Override protected void onPostExecute(Bitmap result) { if (!imv.getTag().toString().equals(path)) { /* The path is not same. This means that this image view is handled by some other async task. We don't do anything and return. */ return; } if(result != null && imv != null){ imv.setVisibility(View.VISIBLE); imv.setImageBitmap(result); }else{ imv.setVisibility(View.GONE); } } } 

Эта запись в блоге разработчиков Android даст вам полный справочный проект для этого в комплекте с кешированием. Просто замените код доступа Http на чтение файлов SD-карты.

Надеюсь, это поможет. После многих поисков у меня есть это рабочее решение.

 public class CustomAdapter extends ArrayAdapter<String>{ /* public CustomAdapter(Context context , String[] video) { super(context,R.layout.custom_row, video); } */ private final Activity context; private final String[] video; static class ViewHolder { public TextView videoTitle; public ImageView videoThumbnail; public int position; public String path; } public CustomAdapter(Activity context, String[] video) { super(context, R.layout.custom_row, video); this.context = context; this.video = video; } @Override public View getView(final int position, View convertView, ViewGroup parent) { LayoutInflater videoInflator = LayoutInflater.from(getContext()); View customView = videoInflator.inflate(R.layout.custom_row, parent, false); ViewHolder viewHolder = new ViewHolder(); viewHolder.position = position; viewHolder.path = video[position]; viewHolder.videoTitle = (TextView) customView.findViewById(R.id.videoTitle); viewHolder.videoThumbnail = (ImageView) customView.findViewById(R.id.videoThumbnail); //rowView.setTag(viewHolder); //} customView.setTag(viewHolder); final String videoItem = video[position]; int index=videoItem.lastIndexOf('/'); String lastString=(videoItem.substring(index +1)); index = lastString.indexOf(".mp4"); lastString=(lastString.substring(0,index)); viewHolder.videoTitle.setText(lastString); new AsyncTask<ViewHolder, Void, Bitmap>() { private ViewHolder v; @Override protected Bitmap doInBackground(ViewHolder... params) { v = params[0]; Bitmap thumb = ThumbnailUtils.createVideoThumbnail(videoItem, MediaStore.Images.Thumbnails.MINI_KIND); return thumb; } @Override protected void onPostExecute(Bitmap result) { super.onPostExecute(result); if (v.position == position) { // If this item hasn't been recycled already, hide the // progress and set and show the image v.videoThumbnail.setImageBitmap(result); } } }.execute(viewHolder); return customView; } 

}

Что бы я сделал (если у вас нет тысяч изображений): 1. создайте структуру данных – простой класс, содержащий отображаемое имя строки, и растровое изображение 2. создайте для него адаптер 3. в методе getView назначьте правильное растровое изображение К правильному ImageView.

В вашем случае, хотя вы можете создать подобную структуру данных, но не содержать растровое изображение, а AsyncTask. В любом случае вам нужно привязать асинтез к строке в один элемент. Массив (или arraylist) таких предметов будет передан вашему адаптеру. Отображается будет изображение и текстовое изображение.

AsyncTask можно отменить с помощью cancel ().

Эй, я нашел решение этой проблемы, просто использую следующую функцию вместо вашей функции

  @Override protected void onPostExecute(Bitmap result) { if (!imv.getTag().toString().equals(rec_id)) { return; } if(result != null && imv != null){ int index = id.indexOf(imv.getTag().toString()); if(list.getFirstVisiblePosition()<=index && index<=list.getLastVisiblePosition()) { imv.setVisibility(View.VISIBLE); imv.setImageBitmap(result); } }else{ imv.setImageBitmap(icon); imv.setVisibility(View.GONE); } } 

Здесь список – это объект listview. Просто передайте объект просмотра списка вашему адаптеру и вставьте эту функцию вместо своей функции onPostExecute.

Возможно, вам стоит попробовать:

 view = mInflater.inflate(mResource,parent,null); 

В этом блоге объясняется аналогичная проблема:

http://www.doubleencore.com/2013/05/layout-inflation-as-intended/