Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
429 views
in Technique[技术] by (71.8m points)

memory management - when to release objects in mono touch / mvvmcross

We are implementing an app which seems to have major memory leaks. For an example we have a view with its corrosponding viewmodel that is registered 38 times in the mono profiler but it should be garbage collected. We have a lot of custom controls etc. but where should these be disposed - as of ios 6 viewdidunload is not called anymore so where should we do our cleanup?

regards

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is a big question... and can't easily be answered for a general case.

In general, if you write nice simple ViewModels and nice simple Views, then you will not get any memory leaks.

However, if you have Views referencing ViewModels, which in turn have callbacks which somehow reference the Views, then it's very possible to get memory leaks - especially if your view models subscribe to events on services.


One particularly nasty situation is when ObjC and C# both have references to objects. There's some discussion of this on http://forums.xamarin.com/discussion/97/correct-way-to-pop-a-dialogviewcontroller-mine-are-staying-in-memory which also references a problem we once had in the SQL bits example - https://github.com/slodge/MvvmCross/issues/19

This may not be the case for your current leak, but it's worth reading Rolf's answer - http://forums.xamarin.com/discussion/comment/535/#Comment_535 - a few times - it's not an entry level explanation, but it makes sense eventually!


So, in order to tackle your current problem...

  1. work out what is leaking

  2. work out why - what is it that is holding on to the references.

  3. fix it.

The key is to invest a decent amount of effort in doing the studying of 1 and 2, before diving in to the wrong fix for 3. There is no point in trying to 'fix it' without really knowing what 'it' is.

The good news is that the Mono profiler - with its built-in tooling to identify what has references to what - is really good for helping with this job.

From your description, I know you've already found this tool - but for anyone else reading, please see - http://docs.xamarin.com/ios/Guides/Deployment%252c_Testing%252c_and_Metrics/Monotouch_Profiler


Once, you've identified what is leaking and why, then step 3 will require some thinking, but will hopefully be easy to answer.

Sometimes the solution is to:

  • Just fix one bad line of code... which line is the hard bit.
  • Use 'back' detection, to work out when to disconnect bindings or events.
  • Use 'willappear', 'willdisappear' to add lifecycle events to change the way you subscribe/unsubscribe from events
  • Use an alternate method than C# events - e.g. use a Messenger such as TinyMessenger (or the MvvmCross plugin messenger) - these have the advantages that they typically use the WeakReference class to avoid leaks.
  • Dispose 'something' at 'an appropriate time' - again working out the 'something' and the 'appropriate time' are the hard parts in this

Whatever happens, don't panic and do tackle this from an engineering perspective. These leaks happen in non-MvvmCross and non-MonoTouch code too - and using MvvmCross with a nice clean IoC architecture should make them easier to find and remove.


If the problem does turn out to be in an MvvmCross binding somewhere, then please do log it as a bug - I take these issues very seriously!

There is still an open bug in a long discussion on the MvvmCross repo about whether we shouldn't use WeakReferences for all our binding code - see https://github.com/slodge/MvvmCross/issues/17 - I've considered doing this - it would help people avoid some bugs... but not all. That issue is still open.


Update: I didn't answer

We have a lot of custom controls etc. but where should these be disposed

The framework should dispose these for you.

If it doesn't then that's probably because something else is leaking and holding on to your View which is then holding on to your Controls. You need to fix that underlying problem, rather than prematurely calling Dispose() on the Controls. Memory leak debugging isn't easy, but is kind of fun (sometimes)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...