Hi I have successfully coded my app to display large png files from thumb view. When the thumb view is clicked the image enlarges to full screen. The problem I'm having is the app runs very slow due to a lack of memory. So I have made an attempt to save memory by using "notifyDrawable" however I am a noobie at this and I have probably gone about this the wrong way. I was wondering if anyone could suggest of a better way to save memory and a way to make my app run more smoothly. Here is the code I've used:
final View thumb1View = findViewById(R.id.thumb_button_1);
thumb1View.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
zoomImageFromThumb(thumb1View, R.drawable.page1);
}
#Override
public void setImageDrawable(Drawable drawable) {
final Drawable previousDrawable = getDrawable();
super.zoomImageFromThumb(drawable);
notifyDrawable(drawable, true);
notifyDrawable(previousDrawable, false);
}
private static void notifyDrawable(Drawable drawable, final boolean isDisplayed) {
if (drawable instanceof English_Infants) {
// The drawable is a CountingBitmapDrawable, so notify it
((English_Infants) drawable).setIsDisplayed(isDisplayed);
} else if (drawable instanceof LayerDrawable) {
// The drawable is a LayerDrawable, so recurse on each layer
LayerDrawable layerDrawable = (LayerDrawable) drawable;
for (int i = 0, z = layerDrawable.getNumberOfLayers(); i < z; i++) {
notifyDrawable(layerDrawable.getDrawable(i), isDisplayed);
}
}
}
});
Related
I'm using the KenBurnsView in the login screen of my App to show several images in the background. The thing is that this images change too abruptly. Isn't a way to implement a fadein/fadeout effect when changing the transitions from one image to another, hooking somewhere in the view API?
This is the code that I'm using to implement the transitions.
private void setupAnimationBackground() {
mBackgroundImageView.setTransitionListener(new KenBurnsView.TransitionListener() {
#DrawableRes int[] mResources = new int[]{
R.drawable.splash1, R.drawable.splash2, R.drawable.splash3,
R.drawable.splash4, R.drawable.splash5, R.drawable.splash6
};
int mIndex = 0;
#Override
public void onTransitionStart(Transition transition) {
mIndex = (mIndex == mResources.length - 1) ? 0 : mIndex + 1;
}
#Override
public void onTransitionEnd(Transition transition) {
mBackgroundImageView.setImageDrawable(ContextCompat.getDrawable(getContext(), mResources[mIndex]));
}
});
}
mBackgroundImageView is a KenBurnsView. I have the images resources in my drawable folder. As you can see I store the references in a resource int array.
Sorry, nope. You need to have two KenBurnsViews one overlapping on top of the other and you handle the crossfading yourself.
I am currently adding ImageViews and setting the images within a ViewHolder. The creation time is not smooth and the first scroll through is not smooth either. Any suggestion or an alternative to having smooth dynamic views within a viewholder?
ViewHolder
class ViewHolderRecipientExpanded extends RecyclerView.ViewHolder {
private LinearLayout mFlagLayout;
//
public ViewHolderRecipientExpanded(View v) {
super(v);
mFlagLayout = (LinearLayout) v.findViewById(R.id.flagLayout);
//
}
public void initiateRecipientsDetails() {
Recipient recipient = objectList.get(getAdapterPosition());
int totalAmountOfCountries = recipient.getFlags() != null ? recipient.getFlags().size() : 0;
//
int countriesLimitedToThree = recipient.getFlags() != null ? (totalAmountOfCountries > 3 ? 3 : totalAmountOfCountries) : 0;
View imageView;
ImageView image;
Drawable drawable;
for (int i = 0; i < countriesLimitedToThree; i++) {
imageView = inflater.inflate(R.layout.view_image_flag, null);
image = (ImageView) imageView.findViewById(R.id.image);
drawable = new BitmapDrawable(context.getResources(), recipient.getFlags().get(i).getFlag());
image.setImageDrawable(drawable);
mFlagLayout.addView(imageView);
}
}
}
Load your images asynchronously, and cache them in memory when they are not in view. This will not block the UI thread when loading images, allowing the user to scroll even if the images aren't loaded yet. Though, it will still take some time for the images to actually appear.
There are also a number of great libraries that will handle this for you:
Picasso
Glide
Fresco
I have a AnimationDrawable that i initialise before starting the animation and recycle it right as it finishes.. the problem is that when i want to start the animation again, i reinitialise everything but still gives an exception
java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap#2bbad018
here's my code
public ImageView radarImageView;
public AnimationDrawable animationDrawable;
public void animationStart() {
// animationStop();
radarImageView = (ImageView) findViewById(R.id.radarIV);
radarImageView.setBackgroundResource(R.drawable.sensor_animation);
animationDrawable = (AnimationDrawable) radarImageView.getBackground();
animationDrawable.start();
}
public void animationStop() {
animationDrawable.stop();
for (int i = 0; i < animationDrawable.getNumberOfFrames(); ++i){
Drawable frame = animationDrawable.getFrame(i);
if (frame instanceof BitmapDrawable) {
((BitmapDrawable)frame).getBitmap().recycle();
}
frame.setCallback(null);
}
animationDrawable.setCallback(null);
// animationDrawable = null;
// radarImageView.setBackgroundResource(0);
}
Why does it not reinitialise the whole thing again?
The problem is because when you Bitmap.recycle() is called on the bitmap you cannot reuse it.
Also as you are calling setBackgroundResources(R.drawable.sensor_animation) you are referring to the same object which its bitmaps were recycled previously.
As a solution, you either have to create a new drawable every time or do not recycle that instance.
If you are worries about the memory usage try to use smaller bitmaps. Also using the correct sizes for different screen densities would help.
I have a 2x27 gridview that's holding white imageviews. I then apply a colorfilter to the imageviews, and every cycle invalidate them. The end result is some animated colors moving around the gridview.
I'm having problems with the gridview randomly showing a white square, instead of the black I initalize everything to. Then, as the colors change every imageview updates, except for the ones that failed to load properly the first time. They always remain white.
Sometimes this doesn't happen. Sometimes it's 1 square, sometimes it's 4 squares.
If I rotate my screen, the stuck white ones go away and everything works. They never come back no matter how many times I rotate/leave the activity and return.
This is me updating the colorfilters. I've checked in here that every grid is getting updated, nothing remains white.
public void updateColors() {
Runnable runnable1 = new Runnable() {
#Override
public void run() {
int r = 0;
int g = 0;
int b = 0;
int y = 0;
while(keepRunning == true){
y = 0;
for(int x=0;x<Consts.VIEWCOUNT;x++){
g = Buffers.offLineBuffer_[y++];
r = Buffers.offLineBuffer_[y++];
b = Buffers.offLineBuffer_[y++];
Drawable myIcon = getResources().getDrawable( ImageAdapter.mThumbIds[x]);
myIcon.setColorFilter(new PorterDuffColorFilter(Color.rgb(r, g, b),PorterDuff.Mode.MULTIPLY));
}
try {
Thread.sleep(55);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
#Override
public void run() {
gridView.invalidateViews();
}
});
}
}
};
new Thread(runnable1).start();
}
This is my adapter
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) { // if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(33, 33));
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(mThumbIds[position]);
return imageView;
}
mThumbsID is just a list of ID's to drawables like below (I shortened it)
public static Integer[] mThumbIdsTemp = {
R.drawable.image1,
R.drawable.image2,
R.drawable.image3,
R.drawable.image4,
}
It just started doing this one day, I haven't been able to track it back to what is causing it, or why it's only ever on the first time it's loaded, but will remain until it's destroyed via rotating the screen.
I've lost over a day trying to track this down, and I'm lost as to what might be causing it.
Any ideas?
I'm using a TransitionDrawable two go between two GradientDrawables, and I'm setting that as the background drawable of a Button. This works fine transitioning between two ColorDrawables, but when I try doing it with GradientDrawables I get some very strange results.
On my 2.3.5 device everything works peachy.
On my 4.2.2 device, the buttons just takes on the first gradient and don't redraw at all.
If I add a call to view.refreshDrawableState() or view.setBackgroundDrawable(drawable) after I've started the transition, it will refresh but things get even weirder:
some buttons work correctly
some buttons flicker at points during the transition
one button, for whatever reason, transitions to black instead of to the second gradient drawable
I am looping the transition with a recursive post to the view, but I don't think that's problem because I get the same problems when I don't do it.
Does anyone know what I can do to fix this? Here's the relevant code:
private static void highlightView(View view, Context context) {
TransitionDrawable drawable;
GradientDrawable d1 = new GradientDrawable(Orientation.TOP_BOTTOM, new int[] { HIGHLIGHT_COLOR_1, HIGHLIGHT_COLOR_G1 });
d1.setCornerRadius(3f);
GradientDrawable d2 = new GradientDrawable(Orientation.TOP_BOTTOM,
new int[] { HIGHLIGHT_COLOR_2, HIGHLIGHT_COLOR_G2 });
d2.setCornerRadius(3f);
drawable = new TransitionDrawable(new Drawable[] {
d1,
d2
});
view.setBackgroundDrawable(drawable);
drawable.setCrossFadeEnabled(true);
animateBackground(drawable, true, view);
}
private static void animateBackground(final TransitionDrawable drawable,
final boolean forward, final View view) {
if (view.getBackground() != drawable) return;
if (forward) {
drawable.startTransition(HIGHLIGHT_CYCLE / 2);
} else {
drawable.reverseTransition(HIGHLIGHT_CYCLE / 2);
}
view.postDelayed(new Runnable() {
#Override
public void run() {
animateBackground(drawable, !forward, view);
}
}, HIGHLIGHT_CYCLE / 2);
view.refreshDrawableState(); //without this, no transition occurs at all
}