ReactiveProperty.MAUI
runceel opened this issue · comments
- Because
SynchronizationContextScheduler
that is default scheduler for ReactiveProperty always executes action later even if it is run on UI thread. needReactivePropertyMauiScheduler
like below:
using Microsoft.Maui.Dispatching;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
namespace Reactive.Bindings.Schedulers;
/// <summary>
/// A scheduler for ReactiveProperty and ReactiveCollection on MAUI.
/// </summary>
public class ReactivePropertyMauiScheduler : LocalScheduler
{
private readonly IDispatcher _dispatcher;
/// <summary>
/// Construct a scheduler from Dispatcher.
/// </summary>
/// <param name="dispatcher">An application's dispatcher</param>
public ReactivePropertyMauiScheduler(IDispatcher dispatcher)
{
_dispatcher = dispatcher;
}
/// <summary>
/// Schedules an action to be executed.
/// </summary>
/// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam>
/// <param name="state">State passed to the action to be executed.</param>
/// <param name="action">Action to be executed.</param>
/// <returns>The disposable object used to cancel the scheduled action (best effort).</returns>
public override IDisposable Schedule<TState>(TState state, Func<IScheduler, TState, IDisposable> action)
{
if (action == null)
{
throw new ArgumentNullException(nameof(action));
}
if (!_dispatcher.IsDispatchRequired)
{
return action(this, state);
}
var d = new SingleAssignmentDisposable();
_dispatcher.Dispatch(() =>
{
if (!d.IsDisposed)
{
d.Disposable = action(this, state);
}
});
return d;
}
/// <summary>
/// Schedules an action to be executed after dueTime.
/// </summary>
/// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam>
/// <param name="state">State passed to the action to be executed.</param>
/// <param name="action">Action to be executed.</param>
/// <param name="dueTime">Relative time after which to execute the action.</param>
/// <returns>The disposable object used to cancel the scheduled action (best effort).</returns>
public override IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action)
{
if (action == null)
{
throw new ArgumentNullException(nameof(action));
}
var dt = Scheduler.Normalize(dueTime);
if (dt.Ticks == 0)
{
return Schedule(state, action);
}
// Note that avoiding closure allocation here would introduce infinite generic recursion over the TState argument
return DefaultScheduler.Instance.Schedule(state, dt, (_, state1) => Schedule(state1, action));
}
}
Close this issue. Because custom dispatcher is NOT needed for ReactivePropertySlim<T>
and ValidatableReactiveProperty<T>
.