Android Custom Listview Загрузка изображений без библиотек
Я хочу загрузить изображения с SD-карты в пользовательский список. Мой список содержит изображение и текстовое представление. Я знаю, что есть много библиотек, которые могут помочь мне достичь этого, но я хочу обойтись без использования таких библиотек.
Проблема:-
Я загружаю изображения из асинхронной задачи. Я вызываю асинхронную задачу изнутри моего getView(). Я получаю изображения только в последнем ряду. То есть, если в моей папке 3 изображения, то в третьем элементе списка отображается только изображение.
Ниже мой код:-
public class MyPhotoAdapter extends BaseAdapter {
private Activity callingActivity;
private ArrayList<String> filePaths = new ArrayList<String>();//contains file path of images
ArrayList<Bitmap> myImages = new ArrayList<Bitmap>();
private int imageWidth;
int position;
ImageView iv_photo;
TextView tv_address;
public MyPhotoAdapter(Activity activity,ArrayList<String> paths,int width)
{
this.callingActivity = activity;
this.filePaths = paths;
this.imageWidth = width;
}
@Override
public int getCount() {
return filePaths.size();
}
@Override
public Object getItem(int i) {
return this.filePaths.get(i);
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
position = i;
LayoutInflater inflater = (LayoutInflater) callingActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.single_photo,viewGroup, false);
iv_photo = (ImageView) row.findViewById(R.id.photoView);
tv_address = (TextView) row.findViewById(R.id.tv_address);
AsyncImageLoader loader = new AsyncImageLoader();
loader.execute(filePaths);
return row;
}
class AsyncImageLoader extends AsyncTask<ArrayList<String>,Bitmap,Void>{
ProgressDialog dialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
dialog = ProgressDialog.show(callingActivity,"Loading Images","Please Wait ....");
}
@Override
protected Void doInBackground(ArrayList<String>... arrays) {
Log.d("Test","Total Images :- "+arrays[0].size());
for(int i = 0; i< arrays[0].size(); i++)
{
Bitmap map = decodeFile(arrays[0].get(i).toString(), 150, 150);
myImages.add(map);
publishProgress(map);
}
return null;
}
@Override
protected void onProgressUpdate(Bitmap... bitmap) {
iv_photo.setImageBitmap(bitmap[0]);
}
@Override
protected void onPostExecute(Void aVoid) {
//super.onPostExecute(aVoid);
dialog.dismiss();
/*for(int i = 0; i < myImages.size(); i ++)
{
iv_photo.setImageBitmap(myImages.get(i));
}*/
}
public Bitmap decodeFile(String filePath, int WIDTH, int HIGHT) {
try {
File f = new File(filePath);
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
final int REQUIRED_WIDTH = WIDTH;
final int REQUIRED_HIGHT = HIGHT;
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_WIDTH
&& o.outHeight / scale / 2 >= REQUIRED_HIGHT)
scale *= 2;
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
}
Изображение отображается только в последнем элементе списка. Другие виды изображений не показывают изображения.
3 ответа
Вы можете следить за этим, чтобы узнать больше об обработке параллелизма.
Я изменил ваш код..... пожалуйста, посмотрите, поможет ли это
public class MyPhotoAdapter extends BaseAdapter {
private Activity callingActivity;
private ArrayList<String> filePaths = new ArrayList<String>();
ArrayList<Bitmap> myImages = new ArrayList<Bitmap>();
private int imageWidth;
int position;
ImageView iv_photo;
TextView tv_address;
public MyPhotoAdapter(Activity activity,ArrayList<String> paths,int width)
{
this.callingActivity = activity;
this.filePaths = paths;
this.imageWidth = width;
}
@Override
public int getCount() {
return filePaths.size();
}
@Override
public Object getItem(int i) {
return this.filePaths.get(i);
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
position = i;
LayoutInflater inflater = (LayoutInflater) callingActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.single_photo,viewGroup, false);
iv_photo = (ImageView) row.findViewById(R.id.photoView);
tv_address = (TextView) row.findViewById(R.id.tv_address);
AsyncImageLoader loader = new AsyncImageLoader(iv_photo);
loader.execute(filePaths);
return row;
}
class AsyncImageLoader extends AsyncTask<ArrayList<String>,Bitmap,Void>{
ProgressDialog dialog;
private final WeakReference<ImageView> imageViewReference;
public AsyncImageLoader(ImageView imageView)
{
imageViewReference = new WeakReference<ImageView>(imageView);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
dialog = ProgressDialog.show(callingActivity,"Loading Images","Please Wait ....");
}
@Override
protected Void doInBackground(ArrayList<String>... arrays) {
Log.d("Test","Total Images :- "+arrays[0].size());
for(int i = 0; i< arrays[0].size(); i++)
{
Bitmap map = decodeFile(arrays[0].get(i).toString(), 150, 150);
myImages.add(map);
publishProgress(map);
}
return null;
}
@Override
protected void onProgressUpdate(Bitmap... bitmap) {
//iv_photo.setImageBitmap(bitmap[0]);
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap[0]);
}
}
}
@Override
protected void onPostExecute(Void aVoid) {
//super.onPostExecute(aVoid);
dialog.dismiss();
/*for(int i = 0; i < myImages.size(); i ++)
{
iv_photo.setImageBitmap(myImages.get(i));
}*/
}
public Bitmap decodeFile(String filePath, int WIDTH, int HIGHT) {
try {
File f = new File(filePath);
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
final int REQUIRED_WIDTH = WIDTH;
final int REQUIRED_HIGHT = HIGHT;
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_WIDTH
&& o.outHeight / scale / 2 >= REQUIRED_HIGHT)
scale *= 2;
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
}
/*
* Retrive photo from path
* and return list of path
*/
public static List<String> RetriveImagePathFromSDCard(String path) {
List<String> tFileList = new ArrayList<String>();
File f = new File(path);
if (f.exists()) {
File[] files = f.listFiles();
Arrays.sort(files);
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (file.isDirectory())
continue;
tFileList.add(file.getPath());
}
}
return tFileList;
}
projectGalleryPhotoPathList = RetriveCapturedImagePath(Constant.ProjectGallery.DIR_PROJECT_GALLERY);
projectGalleryAdapter = new PhotoAdapter(Youractivity.this, projectGalleryPhotoPathList);
В классе адаптера
private List<String> imgPic;
...
...
public ProjectGalleryPhotoAdapter(Context c, List<String> imagePathList) {
context = c;
imgPic = imagePathList;
}
public View getView(final int position, View view, final ViewGroup parent) {
....
....
....
Uri uri = Uri.fromFile(new File(imgPic.get(position)));
imageView.setImageURI(uri);
}
Вы не выполняете переработку представления, к тому времени, когда ваша первая асинхронная задача будет завершена, вы уже создали 3 вида, поэтому вы только применяете изображение к своему последнему виду.
Вы должны справиться с этим параллелизмом, и в документации для Android есть отличный пример по этому поводу.
http://developer.android.com/training/displaying-bitmaps/process-bitmap.html
Вы не должны хранить свои ImageView
и ваш TextView
как глобальная переменная в вашем адаптере, они постоянно меняются.