Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MvvmCross: Using InvokeOnMainThread in plugin

I am extending the Messenger plugin with functionality, which will make it possible to pass messages on the main thread instead of everything happening on a background thread.

I have extended BaseSubscription with a bool for knowing that this subscription needs to be messaged on the main thread. Now I need to be able to use InvokeOnMainThread from the TypedInvoke methods in the actual implementations of the subscriptions.

When I look in the referenced MvvmCross assembly I see that Cirrious.MvvmCross.ViewModels.MvxMainThreadDispatchingObject contains the InvokeOnMainThread method, so the question is how do I get hold of that object so I can invoke the method?

like image 635
Cheesebaron Avatar asked Feb 12 '13 10:02

Cheesebaron


1 Answers

The easiest way to get hold of the UI thread is to inherit from MvxMainThreadDispatchingObject

If the hierarchy won't let you, then the next easiest way is to add the IMvxServiceConsumer marker interface and to then use the GetService<T> extension method:

public class MyClass 
   : MyBaseClass
   , IMvxServiceConsumer
{
    // ...

    private bool DoStuff(Action stuff)
    {
        var dispatcherProvider = this.GetService<IMvxMainThreadDispatcherProvider>();
        var dispatcher = dispatcherProvider.Dispatcher;
        if (dispatcher == null) {
           return false;
        }

        return dispatcher.RequestMainThreadAction(action);
    }
 }

The GetService<T>() static method could also be invoked as a static method if preferred (if you don't want to use IMvxServiceConsumer).


Notes:

  • if you are sharing code between 'Apps' and 'Services'/'BackgroundAgents' you need to be very careful to check for error conditions - there isn't always a UI thread available.

  • Android is particularly special - the UI thread can only really be accessed via the current foreground activity - currently MvvmCross tracks this (via Activity OnStart and OnResume hooks) in the IMvxAndroidCurrentTopActivity service - but there's no guarantee that you will always have a foreground activity running - e.g. if your code ever loads non-MvvmCross activities then obviously MvvmCross won't know about these.

  • You should not hold on to references to the Dispatcher - if you do, then you may be holding Android Activity's in memory beyond their natural lifetimes

  • I guess DoStuff could be put into an extension method too - perhaps I'll add that in v3 (https://github.com/slodge/MvvmCross/issues/150)

like image 178
Stuart Avatar answered Sep 22 '22 19:09

Stuart