Load bitmaps in background in chat in order to make UI smoother
This commit is contained in:
parent
28a6f800a5
commit
617beb7db6
2 changed files with 128 additions and 37 deletions
|
@ -283,7 +283,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
||||||
topBar.setVisibility(View.GONE);
|
topBar.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
contactPicture.setVisibility(View.GONE);
|
contactPicture.setVisibility(View.GONE);
|
||||||
scrollToEnd();
|
//scrollToEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void hideKeyboardVisibleMode() {
|
public void hideKeyboardVisibleMode() {
|
||||||
|
@ -292,7 +292,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
||||||
if (isOrientationLandscape && topBar != null) {
|
if (isOrientationLandscape && topBar != null) {
|
||||||
topBar.setVisibility(View.VISIBLE);
|
topBar.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
scrollToEnd();
|
//scrollToEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChatMessageAdapter extends BaseAdapter {
|
class ChatMessageAdapter extends BaseAdapter {
|
||||||
|
|
|
@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -33,9 +34,13 @@ import org.linphone.mediastream.Log;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
|
@ -95,7 +100,8 @@ public class BubbleChat {
|
||||||
private ImageView statusView;
|
private ImageView statusView;
|
||||||
private LinphoneChatMessage nativeMessage;
|
private LinphoneChatMessage nativeMessage;
|
||||||
private LinphoneChatMessage.LinphoneChatMessageListener fileTransferListener;
|
private LinphoneChatMessage.LinphoneChatMessageListener fileTransferListener;
|
||||||
private static final int SIZE_MAX = 2048;
|
private Context mContext;
|
||||||
|
private static final int SIZE_MAX = 512;
|
||||||
|
|
||||||
@SuppressLint("InflateParams")
|
@SuppressLint("InflateParams")
|
||||||
public BubbleChat(final Context context, LinphoneChatMessage message, LinphoneChatMessage.LinphoneChatMessageListener listener) {
|
public BubbleChat(final Context context, LinphoneChatMessage message, LinphoneChatMessage.LinphoneChatMessageListener listener) {
|
||||||
|
@ -104,6 +110,7 @@ public class BubbleChat {
|
||||||
}
|
}
|
||||||
nativeMessage = message;
|
nativeMessage = message;
|
||||||
fileTransferListener = listener;
|
fileTransferListener = listener;
|
||||||
|
mContext = context;
|
||||||
|
|
||||||
view = new RelativeLayout(context);
|
view = new RelativeLayout(context);
|
||||||
LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||||
|
@ -160,40 +167,7 @@ public class BubbleChat {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
imageView.setVisibility(View.VISIBLE);
|
imageView.setVisibility(View.VISIBLE);
|
||||||
|
loadBitmap(appData, imageView);
|
||||||
Bitmap bm = null;
|
|
||||||
if (appData.startsWith("content")) {
|
|
||||||
try {
|
|
||||||
bm = MediaStore.Images.Media.getBitmap(context.getContentResolver(), Uri.parse(appData));
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
Log.e(e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bm = BitmapFactory.decodeFile(appData);
|
|
||||||
appData = "file://" + appData;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bm != null) {
|
|
||||||
if (bm.getWidth() > bm.getHeight() && bm.getWidth() > SIZE_MAX) {
|
|
||||||
bm = Bitmap.createScaledBitmap(bm, SIZE_MAX, (SIZE_MAX * bm.getHeight()) / bm.getWidth(), false);
|
|
||||||
} else if (bm.getHeight() > bm.getWidth() && bm.getHeight() > SIZE_MAX) {
|
|
||||||
|
|
||||||
bm = Bitmap.createScaledBitmap(bm, (SIZE_MAX * bm.getWidth()) / bm.getHeight(), SIZE_MAX, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
imageView.setImageBitmap(bm);
|
|
||||||
imageView.setTag(appData);
|
|
||||||
imageView.setOnClickListener(new OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
|
||||||
intent.setDataAndType(Uri.parse((String)v.getTag()), "image/*");
|
|
||||||
context.startActivity(intent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TextView msgView = (TextView) layout.findViewById(R.id.message);
|
TextView msgView = (TextView) layout.findViewById(R.id.message);
|
||||||
|
@ -340,4 +314,121 @@ public class BubbleChat {
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return nativeMessage.getStorageId();
|
return nativeMessage.getStorageId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void loadBitmap(String path, ImageView imageView) {
|
||||||
|
if (cancelPotentialWork(path, imageView)) {
|
||||||
|
BitmapWorkerTask task = new BitmapWorkerTask(imageView);
|
||||||
|
Bitmap defaultBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.chat_photo_default);
|
||||||
|
final AsyncBitmap asyncBitmap = new AsyncBitmap(mContext.getResources(), defaultBitmap, task);
|
||||||
|
imageView.setImageDrawable(asyncBitmap);
|
||||||
|
task.execute(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
|
||||||
|
private final WeakReference<ImageView> imageViewReference;
|
||||||
|
public String path;
|
||||||
|
|
||||||
|
public BitmapWorkerTask(ImageView imageView) {
|
||||||
|
path = null;
|
||||||
|
// Use a WeakReference to ensure the ImageView can be garbage collected
|
||||||
|
imageViewReference = new WeakReference<ImageView>(imageView);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode image in background.
|
||||||
|
@Override
|
||||||
|
protected Bitmap doInBackground(String... params) {
|
||||||
|
path = params[0];
|
||||||
|
Bitmap bm = null;
|
||||||
|
|
||||||
|
if (path.startsWith("content")) {
|
||||||
|
try {
|
||||||
|
bm = MediaStore.Images.Media.getBitmap(mContext.getContentResolver(), Uri.parse(path));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
Log.e(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bm = BitmapFactory.decodeFile(path);
|
||||||
|
path = "file://" + path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bm != null) {
|
||||||
|
if (bm.getWidth() >= bm.getHeight() && bm.getWidth() > SIZE_MAX) {
|
||||||
|
bm = Bitmap.createScaledBitmap(bm, SIZE_MAX, (SIZE_MAX * bm.getHeight()) / bm.getWidth(), false);
|
||||||
|
} else if (bm.getHeight() >= bm.getWidth() && bm.getHeight() > SIZE_MAX) {
|
||||||
|
bm = Bitmap.createScaledBitmap(bm, (SIZE_MAX * bm.getWidth()) / bm.getHeight(), SIZE_MAX, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once complete, see if ImageView is still around and set bitmap.
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Bitmap bitmap) {
|
||||||
|
if (isCancelled()) {
|
||||||
|
bitmap = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageViewReference != null && bitmap != null) {
|
||||||
|
final ImageView imageView = imageViewReference.get();
|
||||||
|
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
|
||||||
|
if (this == bitmapWorkerTask && imageView != null) {
|
||||||
|
imageView.setImageBitmap(bitmap);
|
||||||
|
imageView.setTag(path);
|
||||||
|
imageView.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
|
intent.setDataAndType(Uri.parse((String)v.getTag()), "image/*");
|
||||||
|
mContext.startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class AsyncBitmap extends BitmapDrawable {
|
||||||
|
private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
|
||||||
|
|
||||||
|
public AsyncBitmap(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) {
|
||||||
|
super(res, bitmap);
|
||||||
|
bitmapWorkerTaskReference = new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitmapWorkerTask getBitmapWorkerTask() {
|
||||||
|
return bitmapWorkerTaskReference.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean cancelPotentialWork(String path, ImageView imageView) {
|
||||||
|
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
|
||||||
|
|
||||||
|
if (bitmapWorkerTask != null) {
|
||||||
|
final String bitmapData = bitmapWorkerTask.path;
|
||||||
|
// If bitmapData is not yet set or it differs from the new data
|
||||||
|
if (bitmapData == null || bitmapData != path) {
|
||||||
|
// Cancel previous task
|
||||||
|
bitmapWorkerTask.cancel(true);
|
||||||
|
} else {
|
||||||
|
// The same work is already in progress
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No task associated with the ImageView, or an existing task was cancelled
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
|
||||||
|
if (imageView != null) {
|
||||||
|
final Drawable drawable = imageView.getDrawable();
|
||||||
|
if (drawable instanceof AsyncBitmap) {
|
||||||
|
final AsyncBitmap asyncDrawable = (AsyncBitmap) drawable;
|
||||||
|
return asyncDrawable.getBitmapWorkerTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue