Xamarin Forms Android: проблема map.Pins.Clear () - PullRequest
1 голос
/ 23 марта 2020

моя команда разработчиков и я столкнулись с проблемой нашего дистрибутива Android нашего проекта Xamarin. Проблема заключается в следующем: приложение использует наблюдаемую коллекцию объектов и представляет эти объекты в форме представления списка и представления карты с выводами, представляющими объекты. В представлении карты наш код предназначен для подписки на вызов центра обмена сообщениями, который периодически обновляет наблюдаемую коллекцию объектов из нашего API (другая часть проекта). Проблема, с которой мы сталкиваемся, заключается в том, что когда мы вызываем метод PlotPins в блоке кода центра обмена сообщениями, приложение должно сначала получить обновленный список, а затем получить доступ к этому списку, чтобы построить контакты на карте. Каждый раз, когда получено обновление, приложение удалит все контакты с карты, а затем повторно установит контакты на основе обновленного списка (мы знаем, что это неэффективно, но это временное решение). Однако контакты никогда не обновляются. Используя отладчик, мы обнаружили, что после вызова map.Pins.Clear () в PlotPins () приложение переходит к концу метода RequestUpdatedListAsyn c (который периодически возникает для получения обновленного списка и запускается). Центр обмена сообщениями), а затем останавливается.

Наше решение работает для нашей сборки GTK, при этом булавки очищаются и перерисовываются на карте, как и предполагалось, так что, похоже, это проблема Android конкретная c.

Любая помощь будет признательна, спасибо.

Соответствующий код расположен ниже:

СООБЩЕНИЕ ЦЕНТР:


MessagingCenter.Subscribe<object, ObservableCollection<MyObject>>(Application.Current, Constants.ListUpdateContract, (sender, newList) =>
            { 
                //update list
                listUpdater.UpdateList(newList);
                //call method to plot pins again
                PlotPins(map);
            });

PLOTPINS:


private void PlotPins(Map map)
        {
            map.Pins.Clear();
            foreach (MyObject in MyObjects)
            {
                var pin = new Pin
                {
                    Label = MyObject.ID,
                    Address = "Latitude: " + MyObject.Latitude + " " + "Longitude: " + MyObject.Longitude,
                    Type = PinType.Place,
                    Position = new Position(Convert.ToDouble(MyObject.Latitude), Convert.ToDouble(MyObject.Longitude))
                };
                //event handler for when user clicks on pin's info window
                pin.InfoWindowClicked += async (s, args) =>
                {
                    //opens up detail page for pin associated with myObject
                    await Navigation.PushAsync(new DetailPage(MyObject));
                };

                map.Pins.Add(pin);
            }

        }

ЗАПРОС ОБНОВЛЕННОГО СПИСКА ASYN C:


public static async System.Threading.Tasks.Task<bool> RequestUpdatedListAsync()
        {
            if (!_tokenIsGood)
                return false;
            var success = false;
            var response = new HttpResponseMessage();


            try
            {
                response = await _client.GetAsync(Constants. MyObjectDisplayUrl);
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine("Error requesting updated list.");
                System.Diagnostics.Debug.WriteLine(e.Message);
                System.Diagnostics.Debug.WriteLine(e.StackTrace);
                return success;
            }

            response.EnsureSuccessStatusCode();
            success = true;
            var responseBody = await response.Content.ReadAsStringAsync();

            // Update list
            MyObjects.Clear();
            MyObjects = JsonConvert.DeserializeObject<ObservableCollection< MyObject >>(responseBody);

            //Alert subscribed ViewModels to update list
            MessagingCenter.Send<object, ObservableCollection< MyObject >>(Application.Current, Constants.ListUpdateContract, units);


            return success;
        }

1 Ответ

0 голосов
/ 24 марта 2020

Поскольку maps.Pins связан с пользовательским интерфейсом, его необходимо запускать в главном потоке пользовательского интерфейса.

MessagingCenter не всегда публикует / подписывается в основных потоках.

Поэтому, чтобы устранить эту проблему, вызов maps.Pins.Clear() в основном потоке.

Device.BeginInvokeOnMainThread(()=> maps.Pins.Clear());

Кредиты: @ shanranm для упоминания ограничения MessagingCenter для использования основных потоков.

...