Reputation: 2289
I have a custom Listview
- which contains an imageView, text and a checkbox.
I am loading images from dropbox (taking the thumnails or else getting the shared URL to the image) and I am loading them into the custom Listview using an ImageAdapter
.
It is very slow to load the images in a given folder. It takes several seconds just to load a few images, up to a minute if there are dozens, and my app crashes with I assume an Out of Memory exception if there are lots of images.
It seems to be taking about 2 seconds to get the URL from dropbox (or get the Bitmap if you decode the stream). So it is taking 60 seconds to retreive 30 image URLs. This is very excessive (not sure why it is taking so long?)
I am hoping I can improve my code to be a lot faster. I would like to load the images incrementally, i.e. keep the UI responsive and load the images in batches.
I am already using an Async task, so hopefully someone can advise.
Note that I have tried using Universal Image Loader and it still takes a long time to load the images.
I should note that I think the problem is in retrieving the image data from dropbox. The code below retrieves the thumbnail file, and is very slow. I have tried changing the code to instead retrieve the URL link to the image, but again it is very slow to execute and loop.
So is there any way inside of the Loop to get the images, to start displaying the data in the ListView, before the loop has completed? That is - don't wait until the OnTaskCompleted
- but rather start displaying the images inside of the doInBackground
?
Here is the doInBackground
of the Async Task:
@Override
protected Boolean doInBackground(DbxFileSystem... params) {
//Opens thumbnails for each image contained in the dropbox folder
try {
DbxFileSystem fileSystem = params[0];
for (DbxFileInfo fileInfo: fileSystem.listFolder(currentPath)) {
DbxFile file;
//this code below is very slow to execute
try{
if(fileInfo.thumbExists) // if it has a thumbnail then retrieve it
{
file = fileSystem.openThumbnail(fileInfo.path, ThumbSize.XS, ThumbFormat.PNG);
Bitmap image = BitmapFactory.decodeStream(file.getReadStream());
pix.add(image); // image to display in the custom listview
paths.add(fileInfo.path); // path to display in the custom listview
file.close();
}
else
{
//must be a folder if it has no thumb, so add local drawable folder icon
Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.dbfolder);
pix.add(image);
paths.add(fileInfo.path);
}
}catch (DbxException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.gc();
}
}
catch (Exception e) {
e.printStackTrace();
return false;
} finally {
loadingDialog.dismiss();
}
return true;
}
Then in the onTaskCompleted is where we set the Image Adapter:
public void onTaskCompleted(int requestID, ArrayList<Bitmap> urls, ArrayList<DbxPath> path) {
lstView = (ListView) findViewById(R.id.lstView);
this.paths = path;
ImageAdapter adapter = new ImageAdapter(this, urls, paths);
lstView.setAdapter(adapter);
}
This is the getView of the ImageAdapter.java
:
public View getView(int position, View arg1, ViewGroup arg2) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView;
gridView = new View(context);
// inflate image_helper layout
gridView = inflater.inflate(R.layout.list_row, null);
// set images
ImageView imageView = (ImageView) gridView
.findViewById(R.id.list_image);
imageView.setImageBitmap(images.get(position));
TextView textView = (TextView) gridView
.findViewById(R.id.filename);
textView.setText(folderName.get(position).toString());
return gridView;
}
Upvotes: 0
Views: 799
Reputation: 1031
For this you can use Universal Image loader jar universal-image-loader-1.9.2-SNAPSHOT-with-sources.jar
Then adapter is like this
public class LinkAdapter extends ArrayAdapter<MediaModel>{
ArrayList<MediaModel> medias;
Activity context;
ImageLoader imageLoader;
DisplayImageOptions options;
public LinkAdapter(Activity context, int textViewResourceId,
ArrayList<MediaModel> objects) {
super(context, textViewResourceId, objects);
this.medias = objects;
this.context = context;
imageLoader = ImageLoader.getInstance();
imageLoader.init(ImageLoaderConfiguration.createDefault(context));
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_launcher)
.showImageForEmptyUri(R.drawable.ic_launcher)
.showImageOnFail(R.drawable.ic_launcher).cacheInMemory(true)
.cacheOnDisc(true).considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565).build();
}
static class ViewHolder {
TextView title;
TextView description;
ImageView iconImage;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
ViewHolder holder;
if (convertView == null) {
LayoutInflater vi = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.link_row, null);
holder = new ViewHolder();
holder.title = (TextView) v.findViewById(R.id.txt_row_title);
holder.description = (TextView) v.findViewById(R.id.txt_row_description);
holder.iconImage = (ImageView) v.findViewById(R.id.img_row_icon);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
holder.title.setText(medias.get(position).mediaTitle);
holder.description.setText(medias.get(position).mediaInfo);
imageLoader.displayImage(medias.get(position).mediaThumbImgUrl, holder.iconImage,options);
return v;
}
}
Upvotes: 1