Xamarin.Forms ListView ItemsSource - 异步更新NullReferenceException

时间:2016-11-28 18:20:00

标签: listview garbage-collection async-await xamarin.forms itemssource

我在列表视图布局后更新了ListSource上的ItemsSource。我正在使用对Web服务的异步调用来填充表,如果我在创建包含listview的页面之前等待接收数据,它可以正常工作。当我尝试异步加载listview时,我得到一个空引用异常或一个超出范围异常的参数。

- 如果我将传入的数据添加到新的集合中,然后将其指定为itemsSource,我会得到一个ArgumentOutOfRangeException。

- 如果我尝试将新项直接添加到我的itemsSource,我会在插入第一条记录后得到一个空引用异常。

我已经通过调试器确认没有分配空值,并且看起来异常与过早收集垃圾的对象有关 - 我不确定它指的是什么对象

更新 问题仅发生在iOS实现上。列表视图在Android上完全按预期加载传入数据。

这是我的ListView:

public class TransferListView : ListView
{

    public ObservableCollection<TransferCell> transferCells;

    public TransferListView()
    {
        var curData = ESPMobileDS.GetSharedInstance();
        transferCells = new ObservableCollection<TransferCell>();

        ItemTemplate = TransferListView.GetCellTemplate();
        ItemsSource = transferCells;

        RowHeight = 75;
        HorizontalOptions = LayoutOptions.FillAndExpand;
        VerticalOptions = LayoutOptions.FillAndExpand;
        BackgroundColor = ESPResources.Color.SoftBackgroundColorLight2;

        BindingContext = TransferCell.IdentityProperty;

        ItemSelected += async (sender, e) => 
        {
            curData.SelectedTransfer = e.SelectedItem as TransferCell;
            await Navigation.PushAsync(new ItemDetailPage(DetailItemType.Transfer));
        };
    }

    public static DataTemplate GetCellTemplate()
    {
        var cell = new DataTemplate(typeof(TransferCell));
        cell.SetBinding(TransferCell.AccountFromProperty, "AccountFrom");
        cell.SetBinding(TransferCell.AccountToProperty, "AccountTo");
        cell.SetBinding(TransferCell.DateProperty, "Date");
        cell.SetBinding(TransferCell.DescriptionProperty, "Description");
        cell.SetBinding(TransferCell.AmountProperty, "Amount");
        cell.SetBinding(TransferCell.IdentityProperty, "Identity");
        cell.SetBinding(TransferCell.CanDeleteProperty, "CanDelete");
        cell.SetBinding(TransferCell.IsPendingProperty, "IsPending");

        return cell;
    }

    public void ParseAndReceiveServerResponse(string data) {

        var curData = ESPMobileDS.GetSharedInstance();

        var deserializationSettings = new JsonSerializerSettings
        {
            NullValueHandling = NullValueHandling.Ignore,
            MissingMemberHandling = MissingMemberHandling.Ignore
        };

        Dictionary<string, TransferInfoListResponse> transferDict = JsonConvert.DeserializeObject<Dictionary<string, TransferInfoListResponse>>(data, deserializationSettings);

        var transfers = transferDict["d"].Transfers;



        if (transfers != null) {

            Device.BeginInvokeOnMainThread(() => {


                curData.currentPage.RemoveLoadingModal();

                for (int i = 0; i < transfers.Count; i++) {


                    transferCells.Add(new TransferCell
                    {
                        AccountFrom = curData.GetNameForAccountNumber(transfers[i].FromAccount).ToUpper(),
                        AccountTo = curData.GetNameForAccountNumber(transfers[i].ToAccount).ToUpper(),
                        Description = transfers[i].Description,
                        Date = transfers[i].Date,
                        ID = i,
                        Amount = transfers[i].Amount,
                        CanDelete = transfers[i].CanDelete,
                        IsPending = transfers[i].IsPending
                    });



                }

            });
        }

    }
}

以下是其中包含的页面:

public class TransferPage : ESPMobilePage
{
    BindableBoolean amountEntryVisible;
    CustomEntry amountEntry;
    TransferListView transferListView { set; get; }

    AbsoluteLayout addTransferModal { set; get; }

    Picker fromPicker;
    Picker toPicker;
    Picker amountPicker;


    protected override async void OnAppearing() {
        base.OnAppearing();
        var curData = ESPMobileDS.GetSharedInstance();

        await curData.PostToServer(curData.GetPostDataForResponseType(ResponseType.TransferInfoResponse), ESPResources.WebService.URL.GetTransferListMethod).ContinueWith((transferListResponse) => {

            transferListView.ParseAndReceiveServerResponse(transferListResponse.Result);
        });
    }

    public TransferPage ()
    {
        Title = " ";
        Icon = ESPResources.Image.SystemImage.Empty;
        NavigationPage.SetTitleIcon(this, ESPResources.Image.SystemImage.Empty);

        var curData = ESPMobileDS.GetSharedInstance();
        curData.SetCurrentPage(this);

        amountEntryVisible = new BindableBoolean ();
        amountEntryVisible.ShouldBeVisible = false;


        layout = new AbsoluteLayout () {
            HorizontalOptions = LayoutOptions.FillAndExpand,
            VerticalOptions = LayoutOptions.FillAndExpand
        };

        var addTransferTapRecognizer = new TapGestureRecognizer
        {
            Command = new Command(() => {
                OnAddTransfer();
            }),
            NumberOfTapsRequired = 1
        };

        var addButton = new CachedImage
        {
            Source = ESPResources.Image.SystemImage.AddButton,
            Aspect = Aspect.Fill
        };
        addButton.GestureRecognizers.Add(addTransferTapRecognizer);

        CustomNavigationBar navigationBar = new CustomNavigationBar(ESPResources.Text.Symbol.MenuSymbol, ESPResources.FontFamily.SymbolFont, LayoutGen.BuildMenuTapHandler()); 

        transferListView = new TransferListView();

        var unfinishedLayout = LayoutGen.BuildNewCoreLayout(ESPResources.Text.Title.TransferPage.ToUpper(), transferListView, navigationBar);
        var mainLayout = LayoutGen.AddCoreLayoutButton(addButton, unfinishedLayout);

        AbsoluteLayout.SetLayoutBounds (unfinishedLayout, new Rectangle(0,0,1,1));
        AbsoluteLayout.SetLayoutFlags (unfinishedLayout, AbsoluteLayoutFlags.All);

        layout.Children.Add(mainLayout);
        Content = layout;
    }

这是来自NullReferenceException的堆栈跟踪:

 Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: 
    Unhandled Exception:
    System.NullReferenceException: Object reference not set to an instance of an object
      at (wrapper managed-to-native) UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
      at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Users/builder/data/lanes/3969/44931ae8/source/xamarin-macios/src/UIKit/UIApplication.cs:79 
      at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00038] in /Users/builder/data/lanes/3969/44931ae8/source/xamarin-macios/src/UIKit/UIApplication.cs:63 
      at ESPMobile.iOS.Application.Main (System.String[] args) [0x00008] in /Users/clarkin/Projects/ewu-larkinc/ESPMobile/iOS/Main.cs:13 
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: Unhandled managed exception:
    Object reference not set to an instance of an object (System.NullReferenceException)
      at (wrapper managed-to-native) UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
      at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Users/builder/data/lanes/3969/44931ae8/source/xamarin-macios/src/UIKit/UIApplication.cs:79 
      at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00038] in /Users/builder/data/lanes/3969/44931ae8/source/xamarin-macios/src/UIKit/UIApplication.cs:63 
      at ESPMobile.iOS.Application.Main (System.String[] args) [0x00008] in /Users/clarkin/Projects/ewu-larkinc/ESPMobile/iOS/Main.cs:13 
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical: Stacktrace:
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical: 
    Native stacktrace:
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  0   ESPMobileiOS                        0x000000010b21f6bd mono_handle_native_sigsegv + 253
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  1   libsystem_platform.dylib            0x00000001119a3bba _sigtramp + 26
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  2   ???                                 0x000000010b61f99b 0x0 + 4485937563
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  3   libsystem_c.dylib                   0x00000001116fafd7 abort + 129
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  4   ESPMobileiOS                        0x000000010b3c4f0f xamarin_unhandled_exception_handler + 47
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  5   ESPMobileiOS                        0x000000010b21ff8c mono_invoke_unhandled_exception_hook + 92
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  6   ESPMobileiOS                        0x000000010b21ef0f mono_handle_exception_internal + 5119
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  7   ESPMobileiOS                        0x000000010b21db08 mono_handle_exception + 24
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  8   ESPMobileiOS                        0x000000010b19867f mono_amd64_throw_exception + 143
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  9   ???                                 0x000000011dcaa9e7 0x0 + 4794788327
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  10  ESPMobileiOS                        0x000000010b3ca845 xamarin_invoke_trampoline + 7541
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  11  ESPMobileiOS                        0x000000010b3d1cdd xamarin_arch_trampoline + 189
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  12  ESPMobileiOS                        0x000000010b3d3021 xamarin_x86_64_common_trampoline + 110
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  13  UIKit                               0x000000010b80f7b5 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 757
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  14  UIKit                               0x000000010b80fa13 -[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 74
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  15  UIKit                               0x000000010b7e347d -[UITableView _updateVisibleCellsNow:isRecursive:] + 3295
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  16  UIKit                               0x000000010b818d95 -[UITableView _performWithCachedTraitCollection:] + 110
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  17  UIKit                               0x000000010b7ff5ef -[UITableView layoutSubviews] + 222
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  18  UIKit                               0x000000010b766f50 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1237
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  19  QuartzCore                          0x000000010d5bbcc4 -[CALayer layoutSublayers] + 146
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  20  QuartzCore                          0x000000010d5af788 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  21  QuartzCore                          0x000000010d5af606 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  22  QuartzCore                          0x000000010d53d680 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 280
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  23  QuartzCore                          0x000000010d56a767 _ZN2CA11Transaction6commitEv + 475
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  24  QuartzCore                          0x000000010d56b0d7 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 113
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  25  CoreFoundation                      0x000000010ef88e17 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  26  CoreFoundation                      0x000000010ef88d87 __CFRunLoopDoObservers + 391
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  27  CoreFoundation                      0x000000010ef6db9e __CFRunLoopRun + 1198
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  28  CoreFoundation                      0x000000010ef6d494 CFRunLoopRunSpecific + 420
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  29  GraphicsServices                    0x00000001106f5a6f GSEventRunModal + 161
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  30  UIKit                               0x000000010b6a2964 UIApplicationMain + 159
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  31  ???                                 0x000000011f656ca2 0x0 + 4821707938
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical:  32  ???                                 0x000000011f656b30 0x0 + 4821707568
Nov 28 08:26:03 apples-iMac ESPMobileiOS[24684]: critical: 
    =================================================================
    Got a SIGABRT while executing native code. This usually indicates
    a fatal error in the mono runtime or one of the native libraries 
    used by your application.

1 个答案:

答案 0 :(得分:0)

我似乎记得在iOS上更新ObservableCollections存在问题。尝试替换整个事物。例如,在ParseAndReceiveServerResponse方法的底部试试这个:

var tempList = new List<TransferCell>();

for (int i = 0; i < transfers.Count; i++) 
{
    tempList.Add(new TransferCell
    {
        AccountFrom = curData.GetNameForAccountNumber(transfers[i].FromAccount).ToUpper(),
        AccountTo = curData.GetNameForAccountNumber(transfers[i].ToAccount).ToUpper(),
        Description = transfers[i].Description,
        Date = transfers[i].Date,
        ID = i,
        Amount = transfers[i].Amount,
        CanDelete = transfers[i].CanDelete,
        IsPending = transfers[i].IsPending
    });
}

ItemsSource = new ObservableCollection<TransferCell>(tempList);