ViewFlipper not loading bitmap images - android

Hello all having some trouble when I attempt to add an image to a viewflipper page, I am pulling the bitmaps from the db4o database (not sure if it is the encoding or something it uses that is messing me up).
private void setImageView() {
page = (ViewFlipper) findViewById(R.id.viewFlipper1);
int temp = DigPlayDB.getInstance(getBaseContext()).getPlaysDBSize();
for(int j = 0; j < temp; ++j){
test.add(DigPlayDB.getInstance(getBaseContext()).getPlayByInt(j).getImage());
test1.add(DigPlayDB.getInstance(getBaseContext()).getPlayByInt(j).getPlayName());
}
for(int i=0;i<temp; i++)
{
// This will create dynamic image view and add them to ViewFlipper
setFlipperImage(test.get(i));
}
And then for the setting of the image and adding the view to the page
private void setFlipperImage(Bitmap image){
ImageView _image = new ImageView(getApplicationContext());
//_image.setBackgroundDrawable(new BitmapDrawable(getResources(), image));
_image.setImageBitmap(image);
page.addView(_image);
Log.d("db", "" + image);
}
It works right after I add an image to the database but just that image, older images as well as when I restart the application do not load up even though it says they do from a debugging log I set. I am thinking that the last one shows up since it could still be in a cache somewhere, but the older ones that are stored in the database and not in a cache are not encoded correctly or something. Any help would be awesome. Thanks!
Edit: I should mention that "test" is an arraylist of Bitmaps.

Ok, you said in the comment that you store the object as a Bitmap instance. I guess thats a Android or library class.
Don't do that. Only store instances of your own classes. Storing instances of your classes, java.util.collections, arrays and primitives are okay. Everything else is bound to issues: db4o will eagerly try to store any object. This is a issue for library instances. You don't have control of what they do, how they work internally and if they still work after loading.
I think that's whats happening here. As long as the application is running, db4o returns the cached instance of the object, which is fine. After restarting the application, db4o loads the Bitmap object. However the bitmap object isn't intended to be stored with db4o, so it stumbles over wrongly stored internal state.
So, store your picture in a byte-array. Or just as plain file on the SD-card.

Related

can one drawable instance be used on multiple imageView?

in a listview, for each item it needs to show some image(drawable) for different item name. If the name are same they show same image. The drawable is specific and cost some time to make it (need remote resource).
So thought maybe cache the drawable and only build new one if it has not been cached.
saw some article "ANDROID DRAWABLE INSTANCES – DON’T SHARE THEM!"
http://loseyourmarbles.co/2013/09/android-drawable-instances-dont-share/,
and here also need to animate the drawable. But test seems not seeing bad behavior (maybe not tested enough)?
So anyone has had similar requirement and experienced whether one drawable instance could be used on multiple ImageView? Is this approach right way to speed up the listview?
Or can one drawable instance be used on multiple imageView?
HashMap<String, Drawable> mNameToDrawnable = new HashMap<>();
public Drawable getDrawable(Context context, String displayName){
Drawable cachedD = mNameToDrawnable.get(displayName);
if (cachedD != null) {
return cachedD;
}
Drawnable d = makeDrawable(displayName); //new Drawable(context.getResources());, etc ……
d.setDecodeDimensions(100, 100);
mNameToDrawnable.put(displayName, d);
return d;
}
If you want to use the cached drawable in your listview and you're worried about some issues with it you might want to call mutate() on your drawable. This might give you a better understanding : https://android-developers.googleblog.com/2009/05/drawable-mutations.html?m=1

How to change textviews & imageviews of another activity in Android

I have an activity which can take a few seconds to load its content (mainly pictures) from the cloud. Let's say this content is pictures & description from a person. The user can go to pictures & description from another person by clicking on the next button. I'd like to avoid the loading time When this button is clicked.
To do this I have two activities : firstPersonActivity for the first person content, and secondPersonActivity for the second person content.
What I try to do is to load the content of the secondPersonActivity when the user is in the firstPersonActivity, so that the secondPersonActivity can be displayed "directly" (= without needing to load content from the cloud when the next button is clicked in the firstPersonActivity).
But I do not succeed in doing this, I don't know how to modify the views of the secondPersonActivity layout from the firstPersonActivity class.
I tested the following code in my firstPersonActivity but it doesn't work (there is no connexion to the cloud, it's just a test to better understand how it works). R.id.first_image_second_person is the id of my imageview in the secondPersonLayout (= the layout used in the secondPersonActivity).
ImageView firstImageSecondPerson = (ImageView) findViewById(R.id.first_image_second_person);
firstImageSecondPerson.setImageResource(R.drawable.mypicture);
When I click on the next button to go from the firstPersonActivity to the secondPersonActivity, my firstImageSecondPerson imageview is not filled.
Do you see what's wrong ?
Is there a better way to avoid the loading time when the user click on the next button ?
It is not possible to change activity if activity instance is not created. In my opinion to do what You need I would go to single activity with hidden content of second person ( VIEW.INVISIBLE ) and show/hide it when it is needed.
But if second activity must be there, then create some structure for saving bitmaps in memory. In Your code sample You get picture from drawable so we are not talking about some delays, but if images are downloaded from some server then You can create some class which will have those bitmaps created from url and instance of this class can be used on any activity.
So for example Your class for caching pictures would have some method for creating bitmaps like -How to load an ImageView by URL in Android?. And those bitmaps should be saved in some Array or HashMap to have access to it, for example ( pseudo code ):
//some structure for cashing pictures in app
class PictureCache {
static PictureCache instance;
final HashMap<Integer, Bitmap> bitmaps;
//singleton
static PictureCache getInstance(){
if (instance==null)
instance = new PictureCache();
return instance;
}
public PictureCache(){
bitmaps = new HashMap<>;
}
private Bitmap loadBitmap(String url);//#1
public addPicture(Integer personId, String href){
//add to hashMap
bitmaps.put(personId, loadBitmap(href));
}
public Bitmap getPicture(Integer personId){
return bitmaps.get(personId);
}
}
#1 - method from How to load an ImageView by URL in Android?
Using it in first activity:
PictureCache.getInstance().addPicture(12,"http://url.to.bitmap");
Using it in second activity:
Bitmap pic = PictureCache.getInstance().getPicture(12);
Important note - above code was written here and was not tested, it shows solution concept.
Important second note - using such approach with bitmaps in memory can cause to much memory usage
You cannot access the views of SecondActivity before its creation. If you called this activity once only then you are able to access its views by making them static.
One more Solution for this is..
Access the whole data at once and save it in static arraylist with the help of getter-setters. Then on SecondActivity set data from that arraylist.
Hope this will work.
I don't think you can access the view before creating the activity.
You can try to use Glide for caching your images and minimizing loading time.
Try this
Picasso.with(getContext()).load(R.drawable.generatedId).into(imageView);
or
imageView.setImageDrawable(ActivityCompat.getDrawable(getContext(),
R.drawable.generatedID));`

ListView with custom adapter, two types of items and one type with a image gallery. Heap growing up until OutOfMemoryError

I am developing a very complex screen. It has a listview with two types of items: first item, a googlemap and the rest, details of markers in map.
These details are cells with text data and a gallery (fancycoverflow) and its images are downloaded using Picasso library.
When the user moves to another city in the map, the list is refreshing using adapter.notifyDataSetChanged();
It works perfectly: all text data and images are displayed correctly, but memory ram is growing up each time the user moves to another city or scrolls the list. After some time, it throws an OutOfMemoryError.
I cannot show the full code but the getView of the main adapter is something like this:
MainAdapter
getView() {
switch(type) {
case 0: // map
... viewholder pattern...
break;
case 1: // detail with fancycoverflow
... viewholder pattern...
holder.textView.setText("...");
holder.fancy.setAdapter(new FancyCoverFlowCustomAdapter(ctx, images);
...
break;
}
}
The whole text is much long. It has some if conditions to display some textviews or not.
I think the problem is in the setAdapter line. I have tried checking if adapter exists and not creating a new one but images are displaying in the wrong cell.
The FancyCoverFlowCustomAdapter getCoverFlowItem method is:
FancyCoverFlowCustomAdapter
getCoverFlowItem() {
ImageView imageView = null;
if (reuseableView != null) {
imageView = (ImageView) reuseableView;
} else {
imageView = new ImageView(viewGroup.getContext());
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setLayoutParams(new FancyCoverFlow.LayoutParams(FancyCoverFlow.LayoutParams.MATCH_PARENT,
FancyCoverFlow.LayoutParams.WRAP_CONTENT));
}
if (imageView.getDrawable() == null) {
((HomeActivity) context).picasso.load(someurl).config(Bitmap.Config.RGB_565).placeholder(R.drawable.placeholder_loader).resize(((HomeActivity) context).screenWidth, ((HomeActivity) context).cellHeight).centerCrop()
.error(R.drawable.placeholder).into(imageView);
}
return imageView;
}
Picasso object is created in HomeActivity:
picasso = new Picasso.Builder(this).executor(Executors.newSingleThreadExecutor()).build();
The RGB_565 config is used to get better image performance.
I am new on StackOverFlow forum. I will try to update this post to show the little code I have posted as clear as possible, or paste all code I can.
I appreciate so much for your help.
ADITIONAL INFORMATION: a sample workflow:
1 - The app is started: first city is selected, points of interest are downloaded using Retrofit and markers in map and list is generated. Images per cell are displayed in fancycoverflow gallery.
Heap: 32Mb / 39Mb
2 - The user moves to another city, new POIs are downloaded, adapter is notified about the changes so list items changes and new images in galleries are shown.
Heap: 36 / 42Mb
3 - The user moves to another city, same process.
Heap: 41 / 44Mb
And so on.
I think the problem may be bitmaps, that are not correctly recycled. I have searched about how to avoid it with Picasso, but the only thing I have found is using 1 thread and skipping memory cache. Both of them (and separately) didn't work for me, heap size is growing up continuously.
I have read how to load bitmaps efficiently but I think this is not the problem. Bitmaps are loaded by Picasso using resize() method. In addition, Memory Analyzer shows a 70 bitmap allocation after visiting three cities.
Moreover, MAT also shows lots of String allocatiosn (about 12.000). Is it possible that Retrofit, Gson or JSONObject could leak some data? I use all of them to parse server response.
Thank you very much.

Android: keep track of number of objects in cache

I am building a gallery using a ViewPager. Every time a photo is downloaded I immediately cache it in mMemoryCache which is
mMemoryCache = new LruCache<Integer, Bitmap>(cacheSize) {
#Override
protected int sizeOf(Integer key, Bitmap bitmap) {
// The cache size will be measured in bytes rather than number
// of items.
return (bitmap.getRowBytes() * bitmap.getHeight());
}
};
As you can see sizeOf() returns the number if bytes used, which makes sense. My problem is that my ViewPager's adapter needs to know how many pages I have, which would be the number of objects in my cache.
Any ideas on how I can do it? thanks!
I think you should rethink your approach. Usually, when you use some kind of paging (i mean data paging, not the ViewPager), you first add a certain fixed number of items to your Adapter. You can either start downloading the required resources right away, or wait until you really need them. Check in Adapter.onCreateView() if the resource is already downloaded and cached. If yes, get it from there, if not, start an asynchronous download and add the image to the view as soon as you got it. Show a placeholder in the meantime.
When you reach the last item in your adapter, add another batch to it and everything starts over again.
If you really want to know what items are in your LRUCache, override put() and entryRemoved(). There you know what items get added or evicted from the cache. I would advise against this method though.

Can we check whether a duplicate image exists in a list?

I am new to image processing. My SO question is...
I take an image using a camera, then I use this image and check it against a list container. If the list container contains an image that looks like this image then do an operation, otherwise don't.
Example...
I have one image "img_one"
My list contains "image_one,image_two,image_three"
Show list has image_one (i.e. it looks like this image)
So how do I check this image against the items in the list container and show which image looks like this image?
Thanks in advance friends. All ideas are appreciated.
It depends a lot on what do you define by "duplicate".
If you are looking for absolutely identical copies (copy-paste), the game is simple. The approach proposed by Safir, with just a few performance improvements, is Ok.
If you want to find almost-exact duplicates, the job suddenly becomes incredibly difficult. Check out this Checking images for similarity with OpenCV for more info.
Now, back to the "simple" approach, it depends on how many pictures you have to compare. Because comparing each image against all the others in a folder with 1000 images gives you 1.000.000 image reads and comparisons. (Because you cannot store them all in RAM at once, you will have to load and unload them a million times) That way is too much for even a powerful desktop processor.
A simple way would be to use a hashing function (as sha2) for each image, and then compare just the hashes. A good ad-hoc "hashing" for images may be the histogram (although for positives you may want to double-check with memcmp).
And even if you try the brute-force approach (comparing each image pixel with the other), a faster way is to use memcmp() instead of accessing images pixel by pixel.
I don't think there exists such a function in opencv. You have to loop through the pixels yourself and check them one by one. A sample code can be like this:
bool identical(cv::Mat m1, cv::Mat m2)
{
if ( m1.cols != m2.cols || m1.rows != m2.rows || m1.channels() != m2.channels() || m1.type() != m2.type() )
{
return false;
}
for ( int i = 0; i < m1.rows; i++ )
{
for ( int j = 0; j < m1.cols; j++ )
{
if ( m1.at(i, j) != m2.at(i, j) )
{
return false;
}
}
}
return true;
}
If you want to iterate a bit faster through all the pixels, you can look at OpenCV: Matrix Iteration.
i think its little bit time consuming process to compare two images. but you can check it by comparing binaries of that images with each other from adapter or from where you are binding images with ListView.

Categories

Resources