0

我试图执行一个异步动画,它不阻塞主线程。 我试图做的情景:非阻塞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 ..)。

我如何运行我的动画异步?

回答

0

我为我可怜的英语道歉。

在问题中,我删除了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; 
         })); 
       })); 
     }); 
    }); 
}