couple of more optimazations on image loading

This commit is contained in:
Daniel Gultsch 2014-04-25 23:06:20 +02:00
parent bf2d0d5596
commit 645139eb68
7 changed files with 43 additions and 64 deletions

View File

@ -52,6 +52,7 @@
android:id="@+id/conversation_lastimage" android:id="@+id/conversation_lastimage"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="36dp" android:layout_height="36dp"
android:background="#333333"
android:scaleType="centerCrop" /> android:scaleType="centerCrop" />
</LinearLayout> </LinearLayout>

View File

@ -26,9 +26,9 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:maxHeight="288dp"
android:maxWidth="288dp"
android:paddingBottom="2dp" android:paddingBottom="2dp"
android:scaleType="fitXY"
android:background="#333333"
/> />
<TextView <TextView

View File

@ -26,6 +26,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:paddingBottom="2dp" android:paddingBottom="2dp"
android:scaleType="fitXY"
android:background="#333333"
/> />
<TextView <TextView

View File

@ -118,10 +118,10 @@ public class FileBackend {
.getAbsolutePath()); .getAbsolutePath());
} }
public Bitmap getThumbnail(Message message, int size) public Bitmap getThumbnail(Message message, int size, boolean cacheOnly)
throws FileNotFoundException { throws FileNotFoundException {
Bitmap thumbnail = thumbnailCache.get(message.getUuid()); Bitmap thumbnail = thumbnailCache.get(message.getUuid());
if (thumbnail == null) { if ((thumbnail == null)&&(!cacheOnly)) {
Bitmap fullsize = BitmapFactory.decodeFile(getJingleFile(message) Bitmap fullsize = BitmapFactory.decodeFile(getJingleFile(message)
.getAbsolutePath()); .getAbsolutePath());
if (fullsize == null) { if (fullsize == null) {
@ -132,45 +132,6 @@ public class FileBackend {
} }
return thumbnail; return thumbnail;
} }
public void getThumbnailAsync(final Message message, final int size, ImageView imageView, TextView textView) {
Bitmap thumbnail = thumbnailCache.get(message.getUuid());
if (thumbnail == null) {
final WeakReference<ImageView> image = new WeakReference<ImageView>(imageView);
final WeakReference<TextView> text = new WeakReference<TextView>(textView);
new Thread(new Runnable() {
@Override
public void run() {
if (image.get()!=null) {
image.get().setVisibility(View.GONE);
}
if (text.get()!=null) {
text.get().setVisibility(View.VISIBLE);
text.get().setText("loading image");
}
Bitmap fullsize = BitmapFactory.decodeFile(getJingleFile(message)
.getAbsolutePath());
if (fullsize!=null) {
Bitmap thumbnail = resize(fullsize, size);
thumbnailCache.put(message.getUuid(), thumbnail);
if (image.get()!=null) {
image.get().setVisibility(View.VISIBLE);
image.get().setImageBitmap(thumbnail);
}
if (text.get()!=null) {
text.get().setVisibility(View.GONE);
}
}
}
}).start();
} else {
textView.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
imageView.setImageBitmap(thumbnail);
}
}
public void removeFiles(Conversation conversation) { public void removeFiles(Conversation conversation) {
String prefix = context.getFilesDir().getAbsolutePath(); String prefix = context.getFilesDir().getAbsolutePath();

View File

@ -649,42 +649,51 @@ public class ConversationActivity extends XmppActivity {
private Message message = null; private Message message = null;
public BitmapWorkerTask(ImageView imageView) { public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView); imageViewReference = new WeakReference<ImageView>(imageView);
} }
// Decode image in background.
@Override @Override
protected Bitmap doInBackground(Message... params) { protected Bitmap doInBackground(Message... params) {
message = params[0]; message = params[0];
try { try {
return xmppConnectionService.getFileBackend().getThumbnail(message, (int) (metrics.density * 288)); return xmppConnectionService.getFileBackend().getThumbnail(message, (int) (metrics.density * 288),false);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
Log.d("xmppService","file not found!"); Log.d("xmppService","file not found!");
return null; return null;
} }
} }
// Once complete, see if ImageView is still around and set bitmap.
@Override @Override
protected void onPostExecute(Bitmap bitmap) { protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) { if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get(); final ImageView imageView = imageViewReference.get();
if (imageView != null) { if (imageView != null) {
imageView.setImageBitmap(bitmap); imageView.setImageBitmap(bitmap);
imageView.setBackgroundColor(0x00000000);
} }
} }
} }
} }
public void loadBitmap(Message message, ImageView imageView) { public void loadBitmap(Message message, ImageView imageView) {
if (cancelPotentialWork(message, imageView)) { Bitmap bm;
final BitmapWorkerTask task = new BitmapWorkerTask(imageView); try {
final AsyncDrawable asyncDrawable = bm = xmppConnectionService.getFileBackend().getThumbnail(message, (int) (metrics.density * 288), true);
new AsyncDrawable(getResources(), null, task); } catch (FileNotFoundException e) {
imageView.setImageDrawable(asyncDrawable); bm = null;
task.execute(message); }
} if (bm!=null) {
imageView.setImageBitmap(bm);
} else {
if (cancelPotentialWork(message, imageView)) {
imageView.setBackgroundColor(0xff333333);
final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
final AsyncDrawable asyncDrawable =
new AsyncDrawable(getResources(), null, task);
imageView.setImageDrawable(asyncDrawable);
task.execute(message);
}
}
} }
public static boolean cancelPotentialWork(Message message, ImageView imageView) { public static boolean cancelPotentialWork(Message message, ImageView imageView) {
@ -692,16 +701,12 @@ public class ConversationActivity extends XmppActivity {
if (bitmapWorkerTask != null) { if (bitmapWorkerTask != null) {
final Message oldMessage = bitmapWorkerTask.message; final Message oldMessage = bitmapWorkerTask.message;
// If bitmapData is not yet set or it differs from the new data
if (oldMessage == null || message != oldMessage) { if (oldMessage == null || message != oldMessage) {
// Cancel previous task
bitmapWorkerTask.cancel(true); bitmapWorkerTask.cancel(true);
} else { } else {
// The same work is already in progress
return false; return false;
} }
} }
// No task associated with the ImageView, or an existing task was cancelled
return true; return true;
} }

View File

@ -301,16 +301,16 @@ public class ConversationFragment extends Fragment {
viewHolder.image.setVisibility(View.VISIBLE); viewHolder.image.setVisibility(View.VISIBLE);
String[] params = item.getBody().split(","); String[] params = item.getBody().split(",");
if (params.length==3) { if (params.length==3) {
int target = (int) (metrics.density * 288); double target = metrics.density * 288;
int w = Integer.parseInt(params[1]); int w = Integer.parseInt(params[1]);
int h = Integer.parseInt(params[2]); int h = Integer.parseInt(params[2]);
int scalledW; int scalledW;
int scalledH; int scalledH;
if (w <= h) { if (w <= h) {
scalledW = (int) (w / ((double) h / target)); scalledW = (int) (w / ((double) h / target));
scalledH = target; scalledH = (int) target;
} else { } else {
scalledW = target; scalledW = (int) target;
scalledH = (int) (h / ((double) w / target)); scalledH = (int) (h / ((double) w / target));
} }
viewHolder.image.setLayoutParams(new LinearLayout.LayoutParams(scalledW, scalledH)); viewHolder.image.setLayoutParams(new LinearLayout.LayoutParams(scalledW, scalledH));

View File

@ -7,6 +7,7 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import android.graphics.BitmapFactory;
import android.util.Log; import android.util.Log;
import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Account;
@ -78,10 +79,16 @@ public class JingleConnection {
if (acceptedAutomatically) { if (acceptedAutomatically) {
message.markUnread(); message.markUnread();
} }
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file.getAbsolutePath(),options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
message.setBody(""+file.getSize()+","+imageWidth+","+imageHeight);
mXmppConnectionService.databaseBackend.createMessage(message); mXmppConnectionService.databaseBackend.createMessage(message);
mXmppConnectionService.markMessage(message, Message.STATUS_RECIEVED); mXmppConnectionService.markMessage(message, Message.STATUS_RECIEVED);
} }
Log.d("xmppService","sucessfully transmitted file. sha1:"+file.getSha1Sum()); Log.d("xmppService","sucessfully transmitted file. sha1:"+file.getSha1Sum()+" "+message.getBody());
} }
}; };
@ -197,7 +204,7 @@ public class JingleConnection {
public void init(Account account, JinglePacket packet) { public void init(Account account, JinglePacket packet) {
this.status = STATUS_INITIATED; this.status = STATUS_INITIATED;
Conversation conversation = this.mXmppConnectionService.findOrCreateConversation(account, packet.getFrom().split("/")[0], false); Conversation conversation = this.mXmppConnectionService.findOrCreateConversation(account, packet.getFrom().split("/")[0], false);
this.message = new Message(conversation, "receiving image file", Message.ENCRYPTION_NONE); this.message = new Message(conversation, "", Message.ENCRYPTION_NONE);
this.message.setType(Message.TYPE_IMAGE); this.message.setType(Message.TYPE_IMAGE);
this.message.setStatus(Message.STATUS_RECEIVED_OFFER); this.message.setStatus(Message.STATUS_RECEIVED_OFFER);
this.message.setJingleConnection(this); this.message.setJingleConnection(this);
@ -230,6 +237,7 @@ public class JingleConnection {
} }
if (supportedFile) { if (supportedFile) {
this.file.setExpectedSize(Long.parseLong(fileSize.getContent())); this.file.setExpectedSize(Long.parseLong(fileSize.getContent()));
message.setBody(""+this.file.getExpectedSize());
conversation.getMessages().add(message); conversation.getMessages().add(message);
if (this.file.getExpectedSize()<=this.mJingleConnectionManager.getAutoAcceptFileSize()) { if (this.file.getExpectedSize()<=this.mJingleConnectionManager.getAutoAcceptFileSize()) {
Log.d("xmppService","auto accepting file from "+packet.getFrom()); Log.d("xmppService","auto accepting file from "+packet.getFrom());
@ -413,7 +421,7 @@ public class JingleConnection {
this.status = STATUS_TRANSMITTING; this.status = STATUS_TRANSMITTING;
if (connection.needsActivation()) { if (connection.needsActivation()) {
if (connection.getCandidate().isOurs()) { if (connection.getCandidate().isOurs()) {
Log.d("xmppService","candidate "+connection.getCandidate().getCid()+" was our proxy and needs activation"); Log.d("xmppService","candidate "+connection.getCandidate().getCid()+" was our proxy. going to activate");
IqPacket activation = new IqPacket(IqPacket.TYPE_SET); IqPacket activation = new IqPacket(IqPacket.TYPE_SET);
activation.setTo(connection.getCandidate().getJid()); activation.setTo(connection.getCandidate().getJid());
activation.query("http://jabber.org/protocol/bytestreams").setAttribute("sid", this.getSessionId()); activation.query("http://jabber.org/protocol/bytestreams").setAttribute("sid", this.getSessionId());
@ -430,6 +438,8 @@ public class JingleConnection {
} }
} }
}); });
} else {
Log.d("xmppService","candidate "+connection.getCandidate().getCid()+" was a proxy. waiting for other party to activate");
} }
} else { } else {
if (initiator.equals(account.getFullJid())) { if (initiator.equals(account.getFullJid())) {