When importing a contact list from phone contacts to app,there is delay if the list is long-1000 contacts.Want to cut this delay by batch loading ie sending a list with first 10 contacts,render those to screen,second list with the remaining after it

UniversalCoder12 21 Reputation points
2021-06-01T13:08:53.263+00:00

private ObservableCollection<Models.InvitableContact> _contactItems;
public ObservableCollection<Models.InvitableContact> ContactItems
{
get { return _contactItems; }
set { Set(ref _contactItems, value); }
}
private Models.InvitableContact _selectedContact;
public Models.InvitableContact SelectedContact
{
get { return _selectedContact; }
set
{
if (!Set(ref _selectedContact, value)) { return; }
// OnInviteCommandInvoked();
ThreadHelper.RunOnMainUI(async () => await OnInviteCommandInvoked());
}
}
private string _searchContactName;
public string SearchContactName
{
set { Set(ref _searchContactName, value); }
get { return _searchContactName; }
}

 private bool _hasPermission = false; 
 public bool HasPermission 
 { 
     set { Set(ref _hasPermission, value); } 
     get { return _hasPermission; } 
 } 
 private bool _lackPermission = false; 
 public bool LacksPermission 
 { 
     set { Set(ref _lackPermission, value); } 
     get { return _lackPermission; } 
 } 
 public Task OnAppearingAsync() 
 { 
     return Task.Run(async () => await OnAppearing()); 
 } 
 protected async Task OnAppearing() 
 { 
     SelectedContact = null; 
     var appContacts = catalog.Contacts.Get(); 
     if (_contactsRequestCount >= 2 || HasPermission) return; 
     _contactsRequestCount++; 
     //check Contact permission status -- For Android version above 7.0 API 23  
     var hasContactsPermission = await PermissionCheck.HasContactsPermissions(App.Current.MainPage);
     if (hasContactsPermission) 
     { 
         var allContacts = await DependencyService.Get<IContactService>().GetAllContacts(); 
         HasPermission = allContacts.hasPermission; 
         LacksPermission = !allContacts.hasPermission; 
         var invitable = from inphone in allContacts.contacts.Distinct().GroupBy(m => m.Number).Where(m => m.Any()).Select(m => m.FirstOrDefault())
                          join inapp in (appContacts) on inphone.Number equals inapp.Number into grouped
                          from row in grouped.DefaultIfEmpty() 
                          where row == null 
                          orderby inphone.Name ascending 
                          select inphone; 
         // filter out contacts (empty name, etc) 
         var invitableFiltered = (from x in invitable 
                                  where x.Name != null 
                                  where x.Name != "" 
                                  select x); 
         // Don't add/check the same things 
         var invitableContacts = invitableFiltered.Where(m => !SelectableContacts.Any(n => n.Name == m.Name && n.Numbers.Any(nn => nn.Key == m.Number)));
         var contactsToCheck = invitableContacts.GroupBy(c => c.Name); 
         foreach (var ctc in contactsToCheck) 
         { 
             var numbers = new List<KeyValuePair<string, Xamarin.Contacts.PhoneType>>(); 
             foreach (var set in ctc) 
             { 
                 // TODO: - Check the numbers here? 
                 numbers.Add(new KeyValuePair<string, Xamarin.Contacts.PhoneType>(set.Number, set.PhoneType)); 
             } 
             var result = new Models.InvitableContact(ctc.Key, numbers); 
             SelectableContacts.Add(result); 
         } 
         OnSearchContactsFromList(); 
         string json; 
         var user = catalog.Accounts.Get().FirstOrDefault(); 
         int area = Convert.ToInt32(user.AreaCode); 
         string phonenumber = user.Number; 
         bool search_twice = true; // search twice if areacodes are not guaranteed to be included in the list "Contacts".

//here I want to batch load contact list say 10 contacts and rest immediately after it.

json = "{\"AreaCode\":\"" + area + "\", \"phonenumber\":\"" + phonenumber + "\", \"twice\":\"" + search_twice + "\", \"Contacts\": [" + String.Join(",", SelectableContacts.Select(r => r.AsJson())) + "]}";

         RunCheckAndUpdate(json); 

     } 
     else 
     { 
         HasPermission = false; 
         LacksPermission = true; 
         MessagingCenter.Send(this, Constants.MessageCenterConstants.CONTACTS_PERMISSION_DENIED, ContactsPermissionInfo);
     } 
 } 
 private void RunCheckAndUpdate(string json) 
 { 
     Task.Run(async () => await CheckAndUpdate(json)); 
 } 

 private async Task CheckAndUpdate(string json) 
 { 
     var user = catalog.Accounts.Get().FirstOrDefault(); 
     string apitoken = user.ApiToken; 
     try 
     { 
         string url = "https://*************/api/findallusers"; 
         HttpClient httpClient = ApiResourceExtensions.HttpClientWithAuth2(apitoken); 
         var content = new StringContent(json, Encoding.UTF8, "application/json"); 
         var result = await httpClient.PostAsync(url, content); 
         if (result.StatusCode == HttpStatusCode.OK) 
         { 
             // Handle results 
             var body = await result.Content.ReadAsStringAsync(); 
             var definition = new { 
                 Matches = Enumerable.Empty<object>().Select(o => new { Name = "", AreaCode = "", Number = "" }) 
             }; 
             var matches = Newtonsoft.Json.JsonConvert.DeserializeAnonymousType(body, definition).Matches;
             foreach (var contact in SelectableContacts) 
             { 
                 var key = contact.NameAsKey(); 
                 foreach (var match in matches) 
                 { 
                     if (match.Name == key) 
                     { 
                         contact.ExistingNumbers.Add(new KeyValuePair<string, string>(match.AreaCode, match.Number)); 
                     } 
                 } 
                 contact.CheckedExistingNumbers = true; 
             } 
             // Force Re-render 
             ThreadHelper.RunOnMainUI(() => 
             { 
                 ContactItems = new ObservableCollection<Models.InvitableContact>(); 
                 OnSearchContactsFromList(); 
             }); 
         } 
         else 
         { 
             FM.Log.Debug($"Failed to call findusers - StatusCode {result.StatusCode}"); 
         } 
     } 
     catch(Exception e) { 
         FM.Log.Debug("Failed to call findusers", e); 
     } 
 } 
Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,292 questions
SQL Server
SQL Server
A family of Microsoft relational database management and analysis systems for e-commerce, line-of-business, and data warehousing solutions.
12,676 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,221 questions
0 comments No comments
{count} votes

Accepted answer
  1. Kyle Wang 5,531 Reputation points
    2021-06-02T02:36:59.773+00:00

    Hi UniversalCoder12-1951,

    Welcome to our Microsoft Q&A platform!

    Which control do you use to display contact information? ListView or CollectionView?

    If you are using ColectionView, You can set RemainingItemsThreshold and RemainingItemsThresholdReachedCommand to load data incrementally.

    For more info, you can refer to Load data incrementally.

    And here is a simple demo you can refer to.
    CollectionView.xaml

    <CollectionView  
            VerticalScrollBarVisibility="Always"  
            ItemsSource="{Binding ContactToDisplay}"  
            RemainingItemsThreshold="10"  
            RemainingItemsThresholdReachedCommand="{Binding LoadContactCommand}">  
      
        <CollectionView.ItemTemplate>  
            <DataTemplate>  
                <Frame>  
                    <StackLayout>  
                        <Label Text="{Binding Name}"/>  
                        <Label Text="{Binding Number}"/>  
                        <Label Text="{Binding Location}"/>  
                    </StackLayout>  
                </Frame>  
            </DataTemplate>  
        </CollectionView.ItemTemplate>  
    </CollectionView>  
    

    ContactViewModel.cs

    class ContactViewModel : BaseViewModel  
    {  
        public Command LoadContactCommand { get; set; }  
      
        public ContactViewModel()  
        {  
            LoadContactCommand = new Command(LoadContact);  
            InitContact();  
        }  
      
        int startIndex = 1;  
        // add 10 contacts once  
        int showOnScreenCount = 10;  
      
        private void LoadContact()  
        {  
            // add new item to ContactToDisplay  
            ContactToDisplay.AddRange(  
                AllContacts.Skip(showOnScreenCount * startIndex).Take(showOnScreenCount)  
            );  
      
            startIndex++;  
        }  
      
        public List<Person> AllContacts { get; set; }  
      
        ObservableRangeCollection<Person> contactToDisplay;  
      
        public ObservableRangeCollection<Person> ContactToDisplay  
        {  
            get => contactToDisplay;  
            set => SetProperty(ref contactToDisplay, value);  
        }  
      
        private void InitContact()  
        {  
            AllContacts = new List<Person>();  
            for (var i = 1; i <= 1000; i++)  
            {  
                AllContacts.Add(new Person  
                {  
                    Name = "NAME" + i.ToString(),  
                    Number = "NUMBER" + i.ToString(),  
                    Location = "LOCATION" + i.ToString()  
                }); ;  
            }  
      
            contactToDisplay = new ObservableRangeCollection<Person>(AllContacts.Take(showOnScreenCount).ToList());  
        }  
    }  
    

    Regards,
    Kyle


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful