#c# #sqlite #async-await #xamarin.forms
#c# #sqlite #async-await #xamarin.forms
Вопрос:
Я использую nuget sqlite-net-pcl, в моей модели представления я пытаюсь получить список объявлений из моей базы данных
private SQLiteAsyncConnection connection;
public ObservableCollection<Announcement> AnnouncementList { get; private set; }
public AnnouncementsViewModel() {
connection = DependencyService.Get<ISQLiteDb>().GetConnection();
Initialize();
}
public async void Initialize() {
await connection.CreateTableAsync<Announcement>();
var announcements = await connection.Table<Announcement>().ToListAsync();
AnnouncementList = new ObservableCollection<Announcement>(announcements);
System.Diagnostics.Debug.WriteLine("***********************************");
System.Diagnostics.Debug.WriteLine(AnnouncementList.Count);
}
в моем коде позади, в конструкторе:
BindingContext = new AnnouncementsViewModel();
InitializeComponent();
var list = (BindingContext as AnnouncementsViewModel).AnnouncementList;
Ошибка, которую я получаю, такова:
Исключение System.NullReferenceException: ссылка на объект не установлена для экземпляра объекта.
Я устанавливаю точку останова в своей ViewModel, когда она доходит до первого ожидания, она возвращается к исходному коду, и приложение выходит из строя. Я получаю исключение null, потому что список объявлений не заполнен в ViewModel и не печатал звездочки. Как я могу решить эту проблему?
Спасибо
Комментарии:
1. Какова последовательность вызовов исключения?
2.
(BindingContext as AnnouncementsViewModel)
бьюсь об заклад, этоnull
3. @j0ey_wh Я поставил точку останова в этой строке, которая дает мне не удалось разрешить тип: AnnouncementsViewModel
4. @RichardSzalay как мне получить стек вызовов?
5. сделайте это так:
var vieModel = BindingContext as AnnouncementsViewModel
; являетсяvieModel
нулевым?
Ответ №1:
Вы не можете просто вызвать свой асинхронный Initialize()
метод подобным образом. Он вернется немедленно и к тому времени, когда вы приступите к использованию AnnouncementList
, Initialize
еще не завершен, и он по-прежнему равен null.
Это не идеальное решение, но вы должны добавить .Wait()
after Initialize()
, чтобы убедиться, что оно завершено до выхода из конструктора.
Я говорю «не идеально», потому что в зависимости от вашего контекста Wait()
может произойти блокировка. Если это произойдет, вам, вероятно, лучше выполнить эту инициализацию, прежде чем создавать свою ViewModel, используя только «правильное» ожидание и переход AnnouncementsList
в конструктор.
Комментарии:
1. Я не смог выйти. Wait() поскольку Initialize() возвращает void, я изменил ViewModel
2. Чтобы решить эту конкретную проблему, просто измените возвращаемый тип на Task.
3. Когда я запускаю, я получаю только черный экран
Ответ №2:
Новая ViewModel:
public AnnouncementsViewModel() {
connection = DependencyService.Get<ISQLiteDb>().GetConnection();
}
public async void GetAnnouncement() {
await connection.CreateTableAsync<Announcement>();
var announcements = await connection.Table<Announcement>().ToListAsync();
AnnouncementList = new ObservableCollection<Announcement>(announcements); System.Diagnostics.Debug.WriteLine("***********************************");
System.Diagnostics.Debug.WriteLine(AnnouncementList.Count);
}
Затем в моем коде за:
protected override async void OnAppearing() {
(BindingContext as AnnouncementsViewModel).GetAnnouncement();
if ((BindingContext as AnnouncementsViewModel).list != null)
classAnnouncementListView.ItemsSource = (BindingContext as AnnouncementsViewModel).list;
base.OnAppearing();
}
Комментарии:
1. Отредактируйте вопрос, чтобы добавить это, а не добавлять ответ.