Reputation: 60879
I have a ListAdapter that contains a bunch of images that are being downloaded from the internet. When I scroll up and down there seems to be a performance hit and things get jerky. How can I resolve this?
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.message_row, null);
}
STMessage aMessage = messages.get(position);
if (aMessage != null) {
TextView usernameTextView = (TextView) v.findViewById(R.id.usernameTextView);
TextView bodyTextView = (TextView) v.findViewById(R.id.bodyTextView);
TextView dateTextView = (TextView) v.findViewById(R.id.dateTextView);
ImageView avatarImageView = (ImageView)v.findViewById(R.id.avatarImageView);
if (usernameTextView != null) {
usernameTextView.setText(Html.fromHtml(aMessage.getUser_login()));
}
if (bodyTextView != null) {
bodyTextView.setText(aMessage.getBody());
//linkify urls
Linkify.addLinks(bodyTextView, Linkify.WEB_URLS);
//linkify symbols
Pattern symbolMatcher = Pattern.compile("/(?:^|\\s|[\\.(\\+\\-\\,])(?:\\$?)\\$((?:[0-9]+(?=[a-z])|(?![0-9\\.\\:\\_\\-]))(?:[a-z0-9]|[\\_\\.\\-\\:](?![\\.\\_\\.\\-\\:]))*[a-z0-9]+)/i");
String symbolURL = "content://com.stocktwits.activity/symbol/";
Linkify.addLinks(bodyTextView, symbolMatcher, symbolURL);
}
if (dateTextView != null) {
dateTextView.setText(aMessage.getUpdated_at());
}
if (avatarImageView != null) {
imageDownloader.download(aMessage.getAvatar_url(), avatarImageView);
}
}
return v;
}
Upvotes: 0
Views: 932
Reputation: 11828
Here is a nice way to go about it.
At least I think its nice. I did it :)
here is the class I used to load the ImageView in the background.
public class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
private ImageView destination;
private String cachedFile;
private Date startTime;
private DownloadCompletedListener completedListener;
public DownloadImageTask(ImageView destination, String cachedFile, DownloadCompletedListener completedListener)
{
this.destination = destination;
this.cachedFile = cachedFile;
this.startTime = new Date();
this.completedListener = completedListener;
}
protected Bitmap doInBackground(String... urls)
{
Bitmap result = getBitmapFromURL(urls[0]);
if (result != null)
{
try {
FileOutputStream out = new FileOutputStream(HSAppUtil.getFilePath(getFilenameFromUrl(urls[0])));
result.compress(Bitmap.CompressFormat.PNG, 90, out);
} catch (Exception e) {
e.printStackTrace();
}
}
else
{
result = Bitmap.createBitmap(1,1,Config.ARGB_8888);
}
return result;
}
public String getHost() {
return "http://MyMainHost";
}
public Bitmap getBitmapFromURL(String fileUrl) {
String newFileUrl = null;
if (!fileUrl.contains("://"))
{
newFileUrl = getHost() + fileUrl;
}
else
{
newFileUrl = fileUrl;
}
URL myFileUrl = null;
try {
myFileUrl = new URL(newFileUrl);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
HttpURLConnection conn = (HttpURLConnection) myFileUrl.openConnection();
conn.setDoInput(true);
conn.connect();
int length = conn.getContentLength();
InputStream is = conn.getInputStream();
length++;
return BitmapFactory.decodeStream(is);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Bitmap result)
{
synchronized (destination)
{
Date lastUpdated = (Date)destination.getTag();
if (lastUpdated == null || lastUpdated.before(startTime))
{
boolean handled = false;
if (completedListener != null)
{
handled = completedListener.handleDownloadCompleted(destination, result);
}
if (!handled && destination != null)
{
destination.setTag(startTime);
destination.setImageBitmap(result);
}
}
result = null;
}
}
public interface DownloadCompletedListener {
boolean handleDownloadCompleted(ImageView i, Bitmap b);
}
}
then when you want to use it, You would call it like this.
new DownloadImageTask(imView, fileUrl, completedListener).execute(fileUrl);
and send the imView to the UI. it will load the image in when it downloads it.
Please give me your honest feedback.
Upvotes: 0
Reputation: 3380
Maybe by using a Threads pool (queue) and placing a temporal image in the meantime?
Upvotes: 0