Mvvm跨领域访问来自错误的线程



异常

MainViewModel 中来自错误线程的Realm访问

应用程序流

启动屏幕>主活动(异常(

[Activity(MainLauncher = true
, Icon = "@mipmap/ic_launcher"
, Theme = "@style/Theme.Splash"
, NoHistory = true
, ScreenOrientation = ScreenOrientation.Portrait)]
public class SplashScreen : MvxSplashScreenActivity
{
public SplashScreen()
: base(Resource.Layout.SplashScreen)
{
}
}

主要活动

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();
}

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;
}
}
}

应用程序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>();
}

下面的行引发异常。

_realm.All<IsFirstTimeAppStartUpRealm>().Count() > 0

当应用程序通过SplashScreen时,它总是崩溃,如果从MainActivity启动,它会正常工作。

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

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

var dispatcher = Mvx.Resolve<IMvxMainThreadAsyncDispatcher>();
int count;
await dispatcher.ExecuteOnMainThreadAsync(() => 
{
count = _realm.All<IsFirstTimeAppStartUpRealm>().Count();
});

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

https://github.com/runceel/ReactiveProperty

ReactiveProperty是.NET的Rx框架,它将属性封装在一个实例中,该实例根据需要生成INotifyPropertyChanged事件。您将所有这些属性链接在一起,因为它们相互依赖,并且事件在它们之间传播。在属性更改后,您将不再有这些"通知这个,通知那个"的长列表。相反,您可以在代码的单个部分(通常是构造函数(中声明所有成员之间的相互依赖关系

因此,您可以将链的根放在Realm线程上,所有依赖通知都会在该线程上发布。

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

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.
});
}
}

相关内容

  • 没有找到相关文章

最新更新