Обновление списка с помощью вызова API в определенном интервале - xamarin.forms - PullRequest
0 голосов
/ 06 апреля 2020

Я разрабатываю приложение чата в xamarin.forms. Viewmodel, привязанный к моей странице просмотра списка чата, имеет вызов API, который будет извлекать данные чата и привязываться к представлению списка. API будет вызываться только один раз, т.е. когда мы открываем страницу. Я пытаюсь вызывать API каждые 10 секунд и обновлять представление списка, если появляются новые сообщения. Но вместо обновления списка происходит дублирование всех данных. Я думаю, что это нормально, если API снова вызывается , он свяжет все данные. Как я могу обновить это представление списка, если появилось какое-либо новое сообщение? как чат приложение работает. Любая помощь или руководство приветствуется.

Данные API будут назначены входящей и исходящей ячейке в соответствии с параметром.

Моя модель представления;

 public class ChatPageViewModel : INotifyPropertyChanged
    { 
        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public INavigation Navigation { get; set; }
        public string APropertyToSet { get; set; }

        public ObservableCollection<NCMessage> Messages { get; set; } = new ObservableCollection<NCMessage>();
        public ObservableCollection<ChatData> ChatListObj { get; set; }
        public ChatPageViewModel(INavigation navigation)
        {

            // This is how I call the timer

            Device.StartTimer(TimeSpan.FromSeconds(10), () =>
            {

                Device.BeginInvokeOnMainThread(async () =>
                {
                    await loadChatList();
                });

                return true;
            });



            // <--------------- Load chat List API-------------------->


            async Task loadChatList()
            {
                await Task.Run(async () =>
                {
                    try
                    {
                    // API call is the dedicated class for makin API call               
                    APICall callForNotificationList = new APICall("apicallUrl/CallChatList", null, null, "GET");
                        try
                        {
                            ChatListObj = callForNotificationList.APICallResult<ObservableCollection<ChatData>>();
                            if (ChatListObj[0].results.Count != null && ChatListObj[0].results.Count != 0)
                            {
                                if (ChatListObj[0].success)
                                {


                                    foreach (var item in ChatListObj[0].results)
                                    {
                                        if (item.type == "user")
                                        {
                                            if (!string.IsNullOrEmpty(item.message))
                                            {
                                                var message = new NCMessage
                                                {
                                                    Text = item.message.ToString(),
                                                    IsIncoming = "True"
                                                };
                                                Messages.Add(message);

                                            }
                                        }
                                    }
                                }
                                else
                                {
                                //error message
                            }
                            }

                            else
                            {
                            //error message
                        }

                        }
                        catch (Exception e)
                        {

                        }

                    }
                    catch (Exception ex)
                    {

                    }
                });
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

Моя чат XAML

 <ListView                      
             ItemTemplate="{StaticResource MessageTemplateSelector}" 
             ItemsSource="{Binding Messages,Mode=OneWay}" 
             Margin="0"     
             BackgroundColor="Transparent"
             SelectionMode="None"                                  
             FlowDirection="RightToLeft"                               
             HasUnevenRows="True" x:Name="ChatList"
             VerticalOptions="FillAndExpand" 
             SeparatorColor="Transparent"
             >
            </ListView>

Мой XAML.cs

public partial class ChatPage : ContentPage
    {
        ChatPageViewModel vm;
        public ChatPage()
        {
            InitializeComponent();
            this.BindingContext = vm = new ChatPageViewModel(Navigation);
        }
        protected async override void OnAppearing()
        {
            base.OnAppearing();
            await Task.Delay(2000);
            await vm.loadChatList();
        }   
    }

Ответы [ 2 ]

1 голос
/ 07 апреля 2020

Обычные системы чата работают с использованием соединений Socket, так что сервер может push только новые сообщения, которые он получил, в отличие от вашей текущей системы pull. Посмотрите на SignalR, если вы хотите пойти по этому пути, вот хороший пример - Приложение для чата в реальном времени

Что касается вашего текущего кода, есть несколько возможностей:

  1. Как уже упоминал @Jason, вы можете очистить существующие сообщения и добавить их все снова, вы должны использовать RangeObservableCollection , чтобы он не перерисовывал список при каждом добавлении сообщение
  2. Вы можете поддерживать Id для всех сообщений чата и отправлять Id в вызове API, в идеале фильтрация должна выполняться на стороне сервера, без дополнительной нагрузки на клиента.
new APICall("apicallUrl/CallChatList?from_id=<last_message_id>", null, null, "GET")

Если нет last_message_id, отправьте все данные. Это исключает ненужную передачу данных, так как вы отправите только 1 новое сообщение, чем 10 000 предыдущих сообщений:)

1 голос
/ 06 апреля 2020

вы делаете это для каждого сообщения, которое вы извлекаете из своего API, не проверяя, находится ли сообщение уже в коллекции

Messages.Add(message);

у вас есть (как минимум) три варианта

  1. очистить всю коллекцию сообщений перед вызовом API
  2. проверить, существует ли сообщение перед добавлением его в коллекцию
  3. изменить вызов API, чтобы он возвращал только новые сообщения
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...