moagrius / MapView

(Deprecated, prefer https://github.com/moagrius/TileView) Android widget roughly described as a hybrid between com.google.android.maps.MapView and iOS's CATiledLayer
http://moagrius.github.com/MapView/documentation
69 stars 35 forks source link

outOfMemory on galaxy S3 (Log errors but no crash) #21

Closed Shusshu closed 11 years ago

Shusshu commented 11 years ago

I get a lot of out of memory on a Galaxy S3.

I don't know yet how it really happens but my guess is that it's linked to device rotation & putting the app in the background and then switching back to it (via long press on home button)

moagrius commented 11 years ago

Yes, I haven't created any tear-down methods yet, but they definitely need to be available. Should be fairly straightforward - I'll add a todo.

Just for edification - can you see if you get the same when the rotation is locked?

Also, the fastest way to use up memory is to not use every possible tile set - if you don't provide the smallest possible zoom, then it'll be forced to just scale a larger set, so you'll end up with a bunch of small tiles that still take up the same amount of bitmap memory as if they weren't scaled - in experiments with using just one very large tile set, I've seen over 100 tiles forced to render, which will definitely lead to OOM. (not saying you're doing this, but it's probably GTK).

thanks

Shusshu commented 11 years ago

Yup GTK, I'm using 3 zoom levels.

It seems it's stable when the rotation is fixed.

moagrius commented 11 years ago

awesome - I'll provide a teardown method in the next update (hopefully this week)

Shusshu commented 11 years ago

Well now I have a bad news.

I'm setting the scale to 0.27 (my max for this tileset) and I do other things in my app and it crashes "outofmemory" I guess it's the tiles that takes too much memory or aren't recycled

moagrius commented 11 years ago

I'd be interested to see what's happening exactly - can you post the relevant bits? FWIW, it tries to use a new tile set at every 0.5 total scale - so from 0.500001 to 1.0 it uses the largest, from 0.250001 to 0.5 it uses the second largest, 0.125001 to 0.25 the next largest, etc.

If you're setting the scale programmatically, especially during a continuous operation like animation, pinch, scratch, etc, you can temporarily suppress the tile set switch - in this issue #16 I've got todos to expose them. (the switch is already suppressed for built-in pinch and double-tap animations).

Shusshu commented 11 years ago
mapView = new MyMapView(getSherlockActivity());
mapView.addZoomLevel(6493, 4181, "tiles/blankmap_100_%col%_%row%.png");
mapView.addZoomLevel(3247, 2091, "tiles/blankmap_50_%col%_%row%.png");
mapView.addZoomLevel(1367, 1045, "tiles/blankmap_25_%col%_%row%.png");

currentScale = 0.27;
mapView.setScale(currentScale);

mapView.setMarkerAnchorPoints(0.5f, 0.5f);

I'm also adding 50 markers on the map and if you click on the marker it will add balloon markers on top of them

It's failing pretty much right now, I'm looking forward your update

moagrius commented 11 years ago

I bet it's not updating the tile set, so is trying to scale the large set when it should be using the smaller set - if that's so, it's a quick fix.

I'll try to run a test tomorrow about this time.

moagrius commented 11 years ago

I just ran a quick test - everything seems to be working properly, but obviously I don't have your identical setup.

First, I'd try to disable caching as described in #17 and see if that fixes it. If not, Log mapView.getZoom to make sure the appropriate tile set is being used. This will be an integer - 0 will be your smallest tile set, and your largest tile set would be 2 (assuming you have three zoom levels, per your code sample). If it's reporting the correct zoom level for that size, then the only other suggestion I have is to share your project and I'll take a look.

Shusshu commented 11 years ago

Maybe if I set a scale to 0.27 it will try to scale the biggest bitmap ?

If I do a setScale do I need to do a setZoom ? if so there's a problem with setZoom Issue #25

Btw we have different tiles size within a zoom level is that ok? it works...

Shusshu commented 11 years ago

Removing the caching seems to solve the outofmemory problem partly.

I click on a marker and got an outofmemory crash as it couldn't load another activity with a very small bitmap

It would be great to test with your new version with the tearDown

moagrius commented 11 years ago

Maybe if I set a scale to 0.27 it will try to scale the biggest bitmap ?

It shouldn't, and in my test it appeared to be using the correct tile set.

If I do a setScale do I need to do a setZoom ?

No, both are handled independently and update the other (actually, there is no actual "zoom" property - it just calculates it from the scale - all computations includin relative scale, inverse scale, computed scale, actual scale, and zoom - are just derived from the "global" scale value (0-1).

if so there's a problem with setZoom Issue #25

Thanks for catching that - to be honest that was a last minute addition and I hadn't tested it - looked like it should work in theory so I included it, but definitely should have at least tried it myself.

Btw we have different tiles size within a zoom level is that ok? it works...

Each zoom level can have its own tile size, and if they're not uniform (e.g., edge tiles thinner or shorter than "normal" tiles), it should be fine. The tile size is used to position the tiles, and in the math to calculate which should be showing, and for layout of the tile ImageViews - other than that there's no enforcement.

It would be great to test with your new version with the tearDown

I'm slammed this week but will do my best to get it up over the weekend. If you need something before then I could probably post the basic idea.

Shusshu commented 11 years ago

I can wait a bit I guess but you can also post the basic idea ;)

moagrius commented 11 years ago

There should probably be 2 versions - one to "un-render" everything for onPause and orientation changes, and one to complete destroy it for onDestroy.

The first operation will probably require some more finesse, since it'll need to be reconstructed, and is probably not what you're looking for now . The second operation (complete destruction) is a little more straightforward.

The TileManager has one child (a ScalingLayout) for each ZoomLevel. Each of those might have 0 to n children which are ImageViews and contain the tile images. So the first step would be to iterate through all the children of the TileManager (ScalingLayouts), then iterate through each of their children as well (ImageViews), calling setImageBitmap(null); If you're brave, you can grab the backing Bitmap instance from the ImageView and use .recycle() but you won't be able to decode it again later if you do so.

After that, everything is dependency-injected, so if you set the MapView instance to null, the gc should be able to take care of the rest.

moagrius commented 11 years ago

For the record, I should also mention that the cache should be cleared during this operation - since you've disabled caching already, you don't need to worry about it.

moagrius commented 11 years ago

see comments re: #23

Shusshu commented 11 years ago

I still get errors with 1.0.1 while rotation is enabled

moagrius commented 11 years ago

these are out of memory errors? not "asset not found", which are effectively harmless and probably just a result of over-zealous intersection math per #34... LMK (trying to see what still needs debugged and what I can close)

Shusshu commented 11 years ago

Yup they were out of memory errors and the tiles never loaded :(

Benoit Billington

On Sat, Apr 6, 2013 at 9:19 AM, moagrius notifications@github.com wrote:

these are out of memory errors? not "asset not found", which are effectively harmless and probably just a result of over-zealous intersection math per #34 https://github.com/moagrius/MapView/issues/34... LMK (trying to see what still needs debugged and what I can close)

— Reply to this email directly or view it on GitHubhttps://github.com/moagrius/MapView/issues/21#issuecomment-15992161 .

moagrius commented 11 years ago

are you calling mapView.destroy() in the containing Activity's overridden onDestroy method?

Shusshu commented 11 years ago

that does it :)