我在刷新UITableView时遇到问题,至少第一次ViewWillAppear,有时(很少)可能会挂起应用程序。当我离开UIViewController并更改标签项并导航回来时,一切都开始在整个生命周期中完美运行..
拥有如下的ReactiveTableViewSource。
public class ATableViewSource : ReactiveTableViewSourceBase<IAViewModel>
{
WeakReference<AListViewController> _weakContainer;
Lazy<AListViewController> _lazyContainerViewController;
AListViewController Container => _lazyContainerViewController.Value;
public ATableViewSource(AListViewController container,
UITableView tableView,
IReactiveNotifyCollectionChanged<IAViewModel> collection)
: base(tableView, collection,
ATableViewCell.Key,
ATableViewCell.Height,
ATableViewCell.Height)
{
_weakContainer = new WeakReference<AListViewController>(container);
tableView.RegisterNibForCellReuse(ATableViewCell.Nib, ATableViewCell.Key);
_lazyContainerViewController = new Lazy<AListViewController>(() =>
{
AListViewController _container;
_weakContainer.TryGetTarget(out _container);
return _container;
});
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
base.RowSelected(tableView, indexPath);
tableView.DeselectRow(indexPath, false);
var item = ItemAt(indexPath) as IAViewModel;
if (item.IsNotNull())
{
AViewController viewController = new AViewController(item);
Container.NavigationController.PushViewController(viewController, true);
}
}
}
在AListViewController.ViewDidLoad中,我有这个设置。
ATableViewSource _viewSource;
public override void ViewDidLoad()
{
base.ViewDidLoad();
TableView.RowHeight = UITableView.AutomaticDimension;
TableView.EstimatedRowHeight = 350.0f;
TableView.ContentInset = new UIEdgeInsets(8.0f, 0.0f, 8.0f, 0.0f);
_viewSource = new ATableViewSource(this, TableView, ViewModel.TheReactiveList);
TableView.Source = _viewSource;
}
在ViewWillAppear中,我总是刷新数据(ViewModel.TheReactiveList)。
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
ViewModel.RefreshTheReactiveList();
}
AViewModel设置。
public class TheListViewModel : SchedulersViewModelBase, ITheListViewModel
{
public ReactiveList<IAViewModel> TheReactiveList { get; } = new ReactiveList<IAViewModel> { ChangeTrackingEnabled = true };
protected readonly IDataService DataService;
public TheListViewModel(IScheduler mainScheduler,
IScheduler taskPoolScheduler,
IDataService dataService)
: base(mainScheduler, taskPoolScheduler)
{
DataService = dataService;
}
public void RefreshTheReactiveList()
{
DataService.RefreshData()
.SubscribeOn(MainScheduler)
.ObserveOn(MainScheduler)
.Subscribe(ClearDataAndAddRange,
ex => AppObservables.Errors.OnNext(ex))
.DisposeWith(Disposables);
}
void ClearDataAndAddRange(IEnumerable<IAViewModel> data)
{
using (TheReactiveList.SuppressChangeNotifications())
{
TheReactiveList.Clear();
TheReactiveList.AddRange(data);
}
}
}
我必须在这个用例中提到我有一个父UIViewController,它有两个子控制器,每个子控制器都有相同的设置(UITableView,ReactiveTableViewSource,ViewModel.ReactiveList),并且为他们的UIView容器控制隐藏状态,但是我注意到了类似的效果。带有一个UITableView的UIViewController最多需要3秒钟才能在UITableView中显示结果。
为了您的参考,我发布了下面的ReactiveTableViewSourceBase<TViewModel>
,我很久以前就在互联网上发现了这一点,所以可能会产生怀疑。将基类更改为ReactiveTableViewSource<TViewModel>
虽然没有任何区别。
public abstract class ReactiveTableViewSourceBase<TViewModel> : ReactiveTableViewSource<TViewModel>, IInformsEnd
{
private readonly Subject<Unit> _requestMoreSubject = new Subject<Unit>();
private readonly Subject<CGPoint> _scrollSubject = new Subject<CGPoint>();
public IObservable<CGPoint> DidScroll
{
get { return _scrollSubject.AsObservable(); }
}
public IObservable<Unit> RequestMore
{
get { return _requestMoreSubject; }
}
public override void Scrolled(UIScrollView scrollView)
{
_scrollSubject.OnNext(scrollView.ContentOffset);
}
~ReactiveTableViewSourceBase()
{
Console.WriteLine("Destorying " + GetType().Name);
}
protected ReactiveTableViewSourceBase(UITableView tableView, nfloat height, nfloat? heightHint = null)
: base(tableView)
{
tableView.RowHeight = height;
tableView.EstimatedRowHeight = heightHint ?? tableView.EstimatedRowHeight;
}
protected ReactiveTableViewSourceBase(UITableView tableView, IReactiveNotifyCollectionChanged<TViewModel> collection,
Foundation.NSString cellKey, nfloat height, nfloat? heightHint = null, Action<UITableViewCell> initializeCellAction = null)
: base(tableView, collection, cellKey, (float)height, initializeCellAction)
{
tableView.RowHeight = height;
tableView.EstimatedRowHeight = heightHint ?? tableView.EstimatedRowHeight;
}
public override void WillDisplay(UITableView tableView, UITableViewCell cell, Foundation.NSIndexPath indexPath)
{
if (indexPath.Section == (NumberOfSections(tableView) - 1) &&
indexPath.Row == (RowsInSection(tableView, indexPath.Section) - 1))
{
// We need to skip an event loop to stay out of trouble
BeginInvokeOnMainThread(() => _requestMoreSubject.OnNext(Unit.Default));
}
}
public override void RowSelected(UITableView tableView, Foundation.NSIndexPath indexPath)
{
var item = ItemAt(indexPath) as ICanGoToViewModel;
if (item != null)
{
item.GoToCommand.Execute();
}
base.RowSelected(tableView, indexPath);
}
protected override void Dispose(bool disposing)
{
_requestMoreSubject.Dispose();
_scrollSubject.Dispose();
base.Dispose(disposing);
}
}
public interface IInformsEnd
{
IObservable<Unit> RequestMore { get; }
}