General questions:
1. Does calling GC.Collect() anywhere help with your memory use? It could just
be that the GC's allocation limits aren't entirely appropriate, and calling
GC.Collect() will help:
http://docs.xamarin.com/android/advanced_topics/garbage_collection
2. Are there lots of peer instances that can be more quickly collected?
http://docs.xamarin.com/android/advanced_topics/garbage_collection#Cross-VM_Object_Collections
http://docs.xamarin.com/android/advanced_topics/garbage_collection#Helping_the_GC
http://docs.xamarin.com/android/advanced_topics/diagnostics
http://docs.xamarin.com/android/advanced_topics/diagnostics#Global_Reference_Messages
2(b): How is your gref count? You can enable gref logging with:
adb shell setprop debug.mono.log gref
then every monodroid-gref message will contain the current gref count.
On Jun 28, 2012, at 10:57 PM, Liam Houlahan wrote:
> The scenario that I have for my app is. On first start up each day the app
> will do an initial large download. By large I mean a couple of hundred kbs.
> After the large download when the user accesses parent activities for the
> first time they will download all of the child data.
How big is the child data download? How much memory does that approximately
take, post-download? (You can use GC.GetTotalMemory(false) before your web
request and after it returns to see how much memory has been used,
approximately.)
> To update the UI for the large download I am using event handlers in my
> activities assigned to a static event in my service class. For the other
> smaller requests I am using callbacks to the Activities.
You'd need to provide more detail regarding how _exactly_ you do this; done
wrong, this could mean that no Activities can ever be collected (as the static
event is referring to them), so you'd have a steadily increasing gref count and
increasing memory use.
An alternative approach is to instead use
Android.App.Application.SynchronizationContext.Post(...) to invoke something on
the UI thread.
> Some more specific things that I am wandering about are:
>
> - What is the best way to update the UI from async webrequest methods? i.e.
> using action callbacks or events.
Most direct would be Activity.RunOnUiThread(), but if that isn't available then
using Application.SynchronizationContext will work, and in >= 4.2.3 then
System.Threading.SynchronizationContext will actually work (wow!), but note
that SynchronizationContext.Current is [ThreadStatic], so you'd need to either
pass the SynchronizationContext to the worker thread (via a closure?) or use
TAP (which iirc should implicitly pass SynchronizationContext.Current...on
.NET, but I haven't tested on Mono; test accordingly).
> - Should database access and async webrequests be initiated from threads
> separate to the UI thread or is it best to just call them from the UI thread?
> If it is better to use separate threads where should these threads be
> started? e.g. in the activity.
Async web requests should be fine. Database access _may_ be fine; it depends on
the performance characteristics of SQLite and your data set. If you're
confident that it won't block the UI thread for long periods of time, it's
likely safe, but if you're not confident of that you should move the writes
onto another thread.
> - For manually calling the Garbage Collector, should the GC be called after
> each web request? If it should which part of the app should the GC be called
> in and when? i.e in the service class after the download or in the activity
> after displaying the updated results?
Where (1) consistently works in reducing memory use, and (2) is convenient. ;-)
There's a bit of trial and error here...
> - If a user opens an activity that starts a webrequest then goes back opens
> another activity starting more requests how should the app deal with this?
> Should the requests from the first activity be cancelled before starting the
> next etc. If I am using a callback to the activity for an async webrequest
> and the activity is destroyed before the webrequest finishes what is the
> result of this?
Again, it depends on your code structure. The most obvious way would result in
the Async web request referencing the launching Activity, which would thus
prevent the GC from collecting the Activity instance, so when the web request
returns it'll act on a ("dead") Activity instance. This has the added downside
that if the user starts, "exits", then starts your app, you may launch the same
web request twice, downloading more data than is necessary.
Instead, what I would suggest is that your web requests know ~nothing of the
UI. Instead, you should e.g. subclass Android.App.Application [0], and have a
data cache in the Application instance. The Web request would update this data
cache.
Next, Activity.OnCreate() can register with an Application event, and
Activity.OnDestroy() can unregister the Activity with the Application. (Both
are important, to allow the Activity instances to be collectable!) Next,
updates to the Application data cache can raise the Application event, allowing
Activities to be notified that data is available/has changed.
The result of such an architecture is that, with some logic, you can ensure
that only one Web request is generated within a short time period (instead of
one/Activity), all data is (reasonably) up-to-date, and all instances can be
collected when they are no longer used.
- Jon
[0]
https://github.com/xamarin/monodroid-samples/blob/master/SanityTests/Hello.cs#L92
_______________________________________________
Monodroid mailing list
[email protected]
UNSUBSCRIBE INFORMATION:
http://lists.ximian.com/mailman/listinfo/monodroid