image view performance improvement

This commit is contained in:
nuclearfog 2020-06-19 20:11:26 +02:00
parent 117c89b81d
commit 2df5ddad6c
No known key found for this signature in database
GPG Key ID: ED35E22099354A64
4 changed files with 139 additions and 60 deletions

View File

@ -26,6 +26,7 @@ import org.nuclearfog.twidda.adapter.ImageAdapter.OnImageClickListener;
import org.nuclearfog.twidda.backend.ImageLoader;
import org.nuclearfog.twidda.backend.engine.EngineException;
import org.nuclearfog.twidda.backend.helper.ErrorHandler;
import org.nuclearfog.twidda.backend.holder.ImageHolder;
import org.nuclearfog.zoomview.ZoomView;
import java.text.SimpleDateFormat;
@ -143,7 +144,8 @@ public class MediaViewer extends AppCompatActivity implements OnImageClickListen
@Override
public void onImageClick(Bitmap image) {
changeImage(image);
zoomImage.reset();
zoomImage.setImageBitmap(image);
}
@ -201,27 +203,16 @@ public class MediaViewer extends AppCompatActivity implements OnImageClickListen
}
public void setImage(Bitmap image) {
public void setImage(ImageHolder image) {
if (adapter.isEmpty()) {
changeImage(image);
zoomImage.reset();
zoomImage.setImageBitmap(image.getMiddleSize());
image_progress.setVisibility(View.INVISIBLE);
}
adapter.addLast(image);
}
private void changeImage(Bitmap image) {
int width = zoomImage.getMeasuredWidth();
if (width > 0 && image.getWidth() > width) {
float ratio = image.getWidth() / (float) width;
int destHeight = (int) (image.getHeight() / ratio);
image = Bitmap.createScaledBitmap(image, width, destHeight, false);
}
zoomImage.reset();
zoomImage.setImageBitmap(image);
}
private void storeImage(Bitmap image) {
String name = "shitter_" + formatter.format(new Date());
try {

View File

@ -12,21 +12,24 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView.Adapter;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import org.nuclearfog.twidda.backend.holder.ImageHolder;
import java.util.LinkedList;
import java.util.List;
import static android.widget.ListPopupWindow.MATCH_PARENT;
import static android.widget.ListPopupWindow.WRAP_CONTENT;
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
public class ImageAdapter extends Adapter<ImageAdapter.ImageHolder> {
public class ImageAdapter extends Adapter<ViewHolder> {
private static final int PICTURE = 0;
private static final int LOADING = 1;
private OnImageClickListener itemClickListener;
private List<Bitmap> images;
private List<ImageHolder> images;
private boolean loading;
@ -38,11 +41,11 @@ public class ImageAdapter extends Adapter<ImageAdapter.ImageHolder> {
@MainThread
public void addLast(@NonNull Bitmap image) {
public void addLast(@NonNull ImageHolder imageItem) {
int imagePos = images.size();
if (imagePos == 0)
loading = true;
images.add(image);
images.add(imageItem);
notifyItemInserted(imagePos);
}
@ -78,56 +81,73 @@ public class ImageAdapter extends Adapter<ImageAdapter.ImageHolder> {
@NonNull
@Override
public ImageAdapter.ImageHolder onCreateViewHolder(@NonNull final ViewGroup parent, int viewType) {
if (viewType == LOADING) {
public ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, int viewType) {
if (viewType == PICTURE) {
ImageView preview = new ImageView(parent.getContext());
preview.setBackgroundColor(0xffffffff);
preview.setPadding(1, 1, 1, 1);
final ImageItem item = new ImageItem(preview);
preview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = item.getAdapterPosition();
if (pos != NO_POSITION) {
Bitmap img = images.get(pos).getMiddleSize();
itemClickListener.onImageClick(img);
}
}
});
preview.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
int pos = item.getAdapterPosition();
if (pos != NO_POSITION) {
Bitmap img = images.get(pos).getOriginalImage();
itemClickListener.onImageTouch(img);
}
return true;
}
});
return item;
} else {
ProgressBar circle = new ProgressBar(parent.getContext());
LayoutParams param = new LayoutParams(WRAP_CONTENT, MATCH_PARENT);
circle.setLayoutParams(param);
return new ImageHolder(circle);
} else {
return new ImageHolder(new ImageView(parent.getContext()));
return new LoadItem(circle);
}
}
@Override
public void onBindViewHolder(@NonNull ImageAdapter.ImageHolder vh, int index) {
if (vh.view instanceof ImageView) {
final Bitmap image = images.get(index);
ImageView imageView = (ImageView) vh.view;
imageView.setImageBitmap(downscale(image));
imageView.setBackgroundColor(0xffffffff);
imageView.setPadding(1, 1, 1, 1);
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
itemClickListener.onImageClick(image);
}
});
imageView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
itemClickListener.onImageTouch(image);
return true;
}
});
public void onBindViewHolder(@NonNull ViewHolder vh, int index) {
if (vh instanceof ImageItem) {
ImageItem item = (ImageItem) vh;
Bitmap image = images.get(index).getSmallSize();
item.preview.setImageBitmap(image);
}
}
/**
* Holder for image
*/
class ImageItem extends ViewHolder {
final ImageView preview;
private Bitmap downscale(Bitmap image) {
float ratio = image.getHeight() / 256.0f;
int destWidth = (int) (image.getWidth() / ratio);
return Bitmap.createScaledBitmap(image, destWidth, 256, false);
ImageItem(ImageView preview) {
super(preview);
this.preview = preview;
}
}
/**
* Holder for progress circle
*/
class LoadItem extends ViewHolder {
final ProgressBar circle;
static class ImageHolder extends ViewHolder {
final View view;
ImageHolder(View view) {
super(view);
this.view = view;
LoadItem(ProgressBar circle) {
super(circle);
this.circle = circle;
}
}

View File

@ -2,6 +2,7 @@ package org.nuclearfog.twidda.backend;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.os.AsyncTask;
import androidx.annotation.NonNull;
@ -10,6 +11,7 @@ import androidx.annotation.Nullable;
import org.nuclearfog.twidda.activity.MediaViewer;
import org.nuclearfog.twidda.backend.engine.EngineException;
import org.nuclearfog.twidda.backend.engine.TwitterEngine;
import org.nuclearfog.twidda.backend.holder.ImageHolder;
import java.lang.ref.WeakReference;
@ -18,12 +20,15 @@ import java.lang.ref.WeakReference;
*
* @see MediaViewer
*/
public class ImageLoader extends AsyncTask<String, Bitmap, Boolean> {
public class ImageLoader extends AsyncTask<String, ImageHolder, Boolean> {
private static final float PREV_HEIGHT_RATIO = 5.0f;
@Nullable
private EngineException err;
private WeakReference<MediaViewer> callback;
private TwitterEngine mTwitter;
private WeakReference<MediaViewer> callback;
private float previewHeight, zoomPreview;
/**
@ -34,6 +39,10 @@ public class ImageLoader extends AsyncTask<String, Bitmap, Boolean> {
public ImageLoader(@NonNull MediaViewer callback) {
this.callback = new WeakReference<>(callback);
mTwitter = TwitterEngine.getInstance(callback);
Point displaySize = new Point();
callback.getWindowManager().getDefaultDisplay().getSize(displaySize);
zoomPreview = displaySize.x;
previewHeight = displaySize.y / PREV_HEIGHT_RATIO;
}
@ -48,7 +57,8 @@ public class ImageLoader extends AsyncTask<String, Bitmap, Boolean> {
image = BitmapFactory.decodeFile(link);
}
if (image != null) {
publishProgress(image);
ImageHolder images = new ImageHolder(image, previewHeight, zoomPreview);
publishProgress(images);
}
}
return true;
@ -62,9 +72,10 @@ public class ImageLoader extends AsyncTask<String, Bitmap, Boolean> {
@Override
protected void onProgressUpdate(Bitmap[] btm) {
if (callback.get() != null)
callback.get().setImage(btm[0]);
protected void onProgressUpdate(ImageHolder[] images) {
if (callback.get() != null) {
callback.get().setImage(images[0]);
}
}

View File

@ -0,0 +1,57 @@
package org.nuclearfog.twidda.backend.holder;
import android.graphics.Bitmap;
import androidx.annotation.NonNull;
/**
* Container class for Bitmap images and previews
*/
public class ImageHolder {
private Bitmap smallImage, middleImage, fullImage;
public ImageHolder(@NonNull Bitmap fullImage, float smallImageHeight, float middleImageWidth) {
this.fullImage = fullImage;
float ratio = fullImage.getHeight() / smallImageHeight;
int destWidth = (int) (fullImage.getWidth() / ratio);
smallImage = Bitmap.createScaledBitmap(fullImage, destWidth, (int) smallImageHeight, false);
if (middleImageWidth > 0 && fullImage.getWidth() > middleImageWidth) {
ratio = fullImage.getWidth() / middleImageWidth;
int destHeight = (int) (fullImage.getHeight() / ratio);
middleImage = Bitmap.createScaledBitmap(fullImage, (int) middleImageWidth, destHeight, false);
} else {
middleImage = fullImage;
}
}
/**
* get small sized image
*
* @return Image Bitmap
*/
public Bitmap getSmallSize() {
return smallImage;
}
/**
* get Middle sized image
*
* @return Image Bitmap
*/
public Bitmap getMiddleSize() {
return middleImage;
}
/**
* get Original Image
*
* @return Image Bitmap
*/
public Bitmap getOriginalImage() {
return fullImage;
}
}