Xamarin.android MvvmCross-Realm从错误线程访问

Xamarin.android MvvmCross-Realm从错误线程访问,xamarin.android,realm,mvvmcross,viewmodel,Xamarin.android,Realm,Mvvmcross,Viewmodel,例外情况 MainViewModel中不正确线程的领域访问 应用程序流程 SplashScreen>Main活动(例外) main活动 public class MainActivity : MvxAppCompatActivity<MainViewModel>,ViewPager.IOnPageChangeListener,View.IOnTouchListener { protected override void OnCreate(Bundle save

例外情况

MainViewModel中不正确线程的领域访问

应用程序流程

SplashScreen>Main活动(例外)

main活动

public class MainActivity : MvxAppCompatActivity<MainViewModel>,ViewPager.IOnPageChangeListener,View.IOnTouchListener
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            SetContentView(Resource.Layout.activity_tutorial);

            if (ViewModel.IsCompletedOrNot) 
                ViewModel.OpenMainViewModel.Execute();
         }
public类main活动:mvxappcompativity,ViewPager.IOnPageChangeListener,View.IOnTouchListener
{
创建时受保护的覆盖无效(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_教程);
if(ViewModel.IsCompletedOrNot)
ViewModel.OpenMainViewModel.Execute();
}
MainViewModel

     [AddINotifyPropertyChangedInterface]
    public class MainViewModel : MvxViewModel
    {
        private Realm _realm;

        private bool isCompleted = false;

        public TutorialViewModel(IMvxNavigationService navigationService)
        {
            _realm = Mvx.Resolve<Realm>();
        }


    public bool IsCompletedOrNot{                   
                get
                {                                     
                    if (_realm.All<IsFirstTimeAppStartUpRealm>().Count() > 0)
                    {
                        isCompleted=true;

                    }else{

                        isCompleted = false;
                    }

                    return isCompleted;
                }
            }
}
[AddNotifyPropertyChangedInterface]
公共类主视图模型:MvxViewModel
{
私人领域(u领域),;
private bool isCompleted=false;
公共教程视图模型(IMvxNavigationService navigationService)
{
_realm=Mvx.Resolve();
}
公共学校已完成{
得到
{                                     
如果(_realm.All().Count()>0)
{
isCompleted=真;
}否则{
isCompleted=假;
}
返回已完成;
}
}
}
App.CS

           var key = ConfigManager.Settings?.DatabaseEcryption?.EncryptionKey;
            if (key != null && key.Length > 0)
            {
                config.EncryptionKey = key;
            }
            Mvx.RegisterSingleton<Realm>(() => Realm.GetInstance(config));

            Realm _realm = Mvx.Resolve<Realm>();
            int count = _realm.All<IsFirstTimeAppStartUpRealm>().Count();



            //RegisterCustomAppStart<CustomAppStart>();

            // App start
            if (count>0)
            {
                RegisterNavigationServiceAppStart<MainViewModel>(); 
            }
            else
            {
                RegisterNavigationServiceAppStart<OtherViewModel>();
            }
var key=ConfigManager.Settings?.DatabaseEcryption?.EncryptionKey;
if(key!=null&&key.Length>0)
{
config.EncryptionKey=密钥;
}
RegisterSingleton(()=>Realm.GetInstance(config));
Realm _Realm=Mvx.Resolve();
int count=_realm.All().count();
//RegisterCustomAppStart();
//应用程序启动
如果(计数>0)
{
RegisterNavigationServiceAppStart();
}
其他的
{
RegisterNavigationServiceAppStart();
}
下面的行抛出异常

_realm.All<IsFirstTimeAppStartUpRealm>().Count() > 0
\u realm.All().Count()>0
当通过SplashScreen时,应用程序总是崩溃,如果从MainActivity启动,它可以正常工作。

MvvmCross不保证应用程序启动在UI线程上运行。我很可能在线程池线程上运行

为了将一段代码封送到主线程,您可以解析
IMvxMainThreadAsyncDispatcher
(>=6.1.x)或
IMvxMainThreadDispatcher
,并请求在主线程上运行
操作

var dispatcher=Mvx.Resolve();
整数计数;
等待dispatcher.ExecuteOnMainThreadAsync(()=>
{
count=_realm.All().count();
});
MvvmCross不保证应用程序启动在UI线程上运行。我很可能在线程池线程上运行

为了将一段代码封送到主线程,您可以解析
IMvxMainThreadAsyncDispatcher
(>=6.1.x)或
IMvxMainThreadDispatcher
,并请求在主线程上运行
操作

var dispatcher=Mvx.Resolve();
整数计数;
等待dispatcher.ExecuteOnMainThreadAsync(()=>
{
count=_realm.All().count();
});

我有一个相当不错的方法可以从我的应用程序中去除这些代码气味。我最近刚刚开始使用Realm(到目前为止我很喜欢),但我一直使用ReactiveProperty来通知我的视图层VM更改,这真的很好

ReactiveProperty是.NET的一个Rx框架,它将您的属性包装在一个实例中,该实例根据需要生成您的INotifyPropertyChanged事件。您可以将所有这些属性链接在一起,因为它们相互依赖,事件会在其中传播。您不再有“notify of this,notify of this”的长列表财产变动后。 相反,您可以在代码的单个部分(通常是构造函数)中声明所有成员之间的相互依赖关系

因此,您可以将链的根放在领域线程上,并且所有相关通知都在该线程上发布

因此,我的ViewModels看起来像这样(伪代码):

类虚拟机
{
公共反应属性实体{get;set;}
公共ReactiveProperty是FirstLaunch{get;set;}
公共虚拟机(){
var syncCtx=SynchronizationContext.Current;
实体=新的反应属性();
//此属性将在syncCtx上触发其通知。
//记住将视图绑定到“IsFirstLaunch.Value”
IsFirstLaunch=Entity.SubscribeOn(syncCtx)。选择(x=>x.IsFirstLaunch)。ToReactiveProperty()
}
公共异步任务Init()
{
//让我们把领域实例放到syncCtx上。
syncCtx.Post(()=>{
Entity.Value=Realm.Find(typeof(AppStartInfo),0);//或任何您需要的内容。
});
}
}

我有一个相当不错的方法可以从我的应用程序中去除这些代码气味。我最近刚刚开始使用Realm(到目前为止我很喜欢),但我一直使用ReactiveProperty来通知我的视图层VM更改,这真的很好

ReactiveProperty是.NET的一个Rx框架,它将您的属性包装在一个实例中,该实例根据需要生成您的INotifyPropertyChanged事件。您可以将所有这些属性链接在一起,因为它们相互依赖,事件会在其中传播。您不再有“notify of this,notify of this”的长列表财产变动后。 相反,您可以在代码的单个部分(通常是构造函数)中声明所有成员之间的相互依赖关系

因此,您可以将链的根放在领域线程上,并且所有相关通知都在该线程上发布

因此,我的ViewModels看起来像这样(伪代码):

类虚拟机
{
公共反应属性实体{get;set;}
公共ReactiveProperty是FirstLaunch{get;set;}
公共虚拟机(){
var s
_realm.All<IsFirstTimeAppStartUpRealm>().Count() > 0
class VM
{
  public ReactiveProperty<AppStartInfo> Entity { get; set; }
  public ReactiveProperty<bool> IsFirstLaunch { get; set; }

  public VM(){
    var syncCtx = SynchronizationContext.Current;
    Entity = new ReactiveProperty<AppStartInfo>();

    // this property will fire its notifications on the syncCtx.
    // remember to bind your view to "IsFirstLaunch.Value"
    IsFirstLaunch = Entity.SubscribeOn(syncCtx).Select(x => x.IsFirstLaunch).ToReactiveProperty()
  }

  public async Task Init()
  {
    // let's get our realm instance on to the syncCtx.
    syncCtx.Post(() => {
        Entity.Value = Realm.Find(typeof(AppStartInfo), 0); // or whatever you need.
    });
  }
}