Xamarin表单ListView程序刷新在页面加载时不会在Android上停止

时间:2017-02-10 17:25:20

标签: c# android visual-studio-2015 xamarin.forms pull-to-refresh

我在Visual Studio 2015中有一个带有<div class="col-md-6" style="background-color: lightblue;display: flex;align-items: center;"> 的Portable项目,通过以下函数ListView通过API调用填充了一些数据:

refreshData

async Task refreshData() { myListView.BeginRefresh(); var apiCallResult = await App.Api.myApiGetCall(); myListView.ItemsSource = apiCallResult; myListView.EndRefresh(); }

中调用
refreshData()

一切正常,但在Android上,当初始加载页面时,刷新指示器没有停止或消失在protected override void OnAppearing() { base.OnAppearing(); refreshData(); } 上。该页面位于EndRefresh()中,因此我可以转到另一个标签页然后返回此页面,并在完成API调用后正确启动和停止刷新指示符。

为什么在Android最初加载页面时刷新不会停止?任何帮助将不胜感激。

注意:当我在iOS上运行时,此功能完全正常。

到目前为止,我已尝试过:

  1. TabbedPage替换为myListView.BeginRefresh(),将myListView.IsRefreshing = true替换为myListView.EndRefresh()

  2. 使用myListView.IsRefreshing = false

  3. 使用Device.BeginInvokeOnMainThread(() => {//update list and endRefresh})代替async void refreshData()

3 个答案:

答案 0 :(得分:2)

试试这个:

async void refreshData()
{
    Device.BeginInvokeOnMainThread(() => {
        myListView.BeginRefresh();
        var apiCallResult = await App.Api.myApiGetCall();
        myListView.ItemsSource = apiCallResult;
        myListView.EndRefresh();
    });
}

显然,不需要&#34;任务&#34;了。

如果只在Android中出现错误,那么它可能只是Android处理线程的方式。它不允许线程直接更改可视元素。有时,当我们尝试这样做时,它会抛出一个无声的异常,代码操作没有实际效果。

答案 1 :(得分:1)

个人而言,在 Page Contructor 中启动ListView刷新并在加载数据后将其停止时,我会遇到此问题。有时(经常)Xamarin.Forms ListView不会取消刷新动画。

我相信您在Android SwipeRefreshLayout上遇到了一个非常普遍的问题:调用setRefreshing(false)之后,它可能不会停止刷新动画。本机Android开发人员使用以下方法:

swipeRefreshLayout.post(new Runnable() {
    @Override
        public void run() {
            mSwipeRefreshLayout.setRefreshing(refreshing);
    }
});

有趣的是,Xamarin.Forms在设置初始刷新状态(code)时会使用此方法;但是,这还不够。您需要一个自定义渲染器:

public class ExtendedListViewRenderer : ListViewRenderer
{
    /// <summary>
    /// The refresh layout that wraps the native ListView.
    /// </summary>
    private SwipeRefreshLayout _refreshLayout;

    public ExtendedListViewRenderer(Android.Content.Context context) : base(context)
    {
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _refreshLayout = null;
        }
        base.Dispose(disposing);
    }

    protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
    {
        base.OnElementChanged(e);
        _refreshLayout = (SwipeRefreshLayout)Control.Parent;
    }

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == ListView.IsRefreshingProperty.PropertyName)
        {
            // Do not call base method: we are handling it manually
            UpdateIsRefreshing();
            return;
        }
        base.OnElementPropertyChanged(sender, e);
    }

    /// <summary>
    /// Updates SwipeRefreshLayout animation status depending on the IsRefreshing Element 
    /// property.
    /// </summary>
    protected void UpdateIsRefreshing()
    {
        // I'm afraid this method can be called after the ListViewRenderer is disposed
        // So let's create a new reference to the SwipeRefreshLayout instance
        SwipeRefreshLayout refreshLayoutInstance = _refreshLayout;

        if (refreshLayoutInstance == null)
        {
            return;
        }

        bool isRefreshing = Element.IsRefreshing;
        refreshLayoutInstance.Post(() =>
        {
            refreshLayoutInstance.Refreshing = isRefreshing;
        });
    }
}

答案 2 :(得分:0)

您需要遵循MVVM模式

在ViewModel上,您需要:

  • 实施INotifyPropertyChanged
  • 定义以下属性: private bool _IsRefreshing; public bool IsRefreshing { get{return _IsRefreshing;} set{SetProperty(ref _IsRefreshing, value;} /*So every time the property changes the view is notified*/ }

  • 定义获取数据的方法,在您的情况下refreshData()

  • 在需要时切换IsRefreshing true / false

在您的网页上,您需要:

  • 将listview itemSource绑定到具有SetPropertyValue
  • 的VM属性
  • 将ListView.IsRefreshing绑定到ViewModel的IsRefresging:

    MyListView.SetBinding<MyViewModel>(ListView.IsRefreshing, vm => vm.IsRefresging);

Here是一篇很棒的文章,讨论了INotifyPropertyChanged