非阻塞UI线程动画
问题描述:
我试图执行一个异步动画,它不阻塞主线程。 我试图做的情景:非阻塞UI线程动画
用户点击一个按钮,并在一段时间后视图模型属性 改变其状态。
在MvxFragment视图我订阅
OnPropertyChanged
事件,如果所需的属性已更改,我执行动画(显示通知 用户几秒钟)。
我坚持在动画过程中的应用程序没有响应:
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var ignore = base.OnCreateView(inflater, container, savedInstanceState);
var view = this.BindingInflate(Resource.Layout.MyView, null);
ViewModel.WeakSubscribe(PropertyChanged);
return view;
}
private void PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "IsSaved")
{
if (ViewModel.IsSaved)
{
ShowSavedPopup();
}
}
}
private void ShowSavedPopup()
{
var dispatcher = Mvx.Resolve<IMvxMainThreadDispatcher>();
dispatcher.RequestMainThreadAction(() =>
{
var popupView = View.FindViewById(Resource.Id.popup);
popupView.Alpha = 0.0f;
popupView.Animate()
.SetDuration(4000)
.Alpha(1f)));
});
}
我也尝试了不同的方式来运行动画异步,但他们没有工作(等待Task.Run, Activity.RunOnUiThread ..)。
我如何运行我的动画异步?
答
我为我可怜的英语道歉。
在问题中,我删除了brewity的动画场景的结束行,但问题隐藏在那里。 在我的情况下,问题是使用Thread.Sleep。
冻结了主UI线程。
我应该使用async Task来代替。并使用Task.Delay来显示所需时间段的弹出窗口。
工作的解决方案将是:
private async void ShowSavedPopup()
{
// check if animation is in progress
if (_isBusy) return;
_isBusy = true;
await Task.Factory.StartNew(() =>
{
_popupView.Post(() =>
{
_popupView.Visibility = ViewStates.Visible;
_popupView.Alpha = 0.0f;
_popupView.Animate()
.SetDuration(400)
.Alpha(1f)
.WithEndAction(new Runnable(async() =>
{
await Task.Delay(2000);
_popupView.Animate()
.SetDuration(400)
.Alpha(0.0f)
.WithEndAction(new Runnable(() => {
_popupView.Visibility = ViewStates.Gone;
isBusy = false;
}));
}));
});
});
}