+1

Xamarin-LoadMore Trong Xamarin Part 3

Chào mọi người! Hôm nay tiếp tục với xamarin Form, mình sẽ làm một ví dụ về LoadMore cho list.

Về loadmore là gì thì bạn cứ hiểu đơn giản nếu bạn có 1 list danh sách lớn, khi chúng ra không thể get tất cả data này một lần và đổ nó vào list view được. Ở đây việc "Không được" là do nếu làm như vậy sẽ rất nguy hiểm vì nó làm tràn bộ nhớ của app và bắn ra lỗi hoặc nếu muốn lấy list full như thế thì sever phải làm và trả lại dữ liệu rất lớn, thời gian chờ đợi request response cũng sẽ rất lâu khi đó người dùng có thể thấy app của mình bị đơ và rất chuối 😄 Nếu bạn nào muốn hiểu kỹ cách xử lý hay vì sao ta cần loadmore thì có thể nhờ bác Mr Gồ nha, mình ko rành nói kiểu chuyên nghiệp lắm.

Trước tiên để làm cái loadmore thì mình sẽ sửa cái service get employee của bài trước với hai param là index và pagesize DemoAPI/EmployeeController.cs

        ...
        // GET: api/Employees
        public IQueryable<Employee> GetEmployees(int index, int pagesize)
        {
            //return db.Employees;
            var result = db.Employees.OrderBy(a => a.Id).Skip(pagesize * (index -1)).Take(pagesize);
            return result;
        }
        ...

Sau này nếu bạn nào muốn tăng hiệu suất chỗ get này thì có thể dùng sp hoặc cách khác nếu muốn. Ở đây đơn giản là mỗi lần bên phía mobie app gọi hàm loadmore thì nó sẽ truyền lên hai param: 1 là index của page hiện tại, 2 là kích thước page hay tổng số item muốn load mỗi lần.

Giờ chúng ta sẽ sửa một tí ở Xamarin form. Tại EmployeeServices ta sẽ update lại hàm GetEmployees như sau:

        public async Task<List<Employee>> GetEmplyees(int index, int pagesize)
        {
            RestClient<Employee> restClient = new RestClient<Employee>();
            var employeeList = await restClient.GetAsync(index, pagesize);
            return employeeList;
        }

Tại EmployeeViewModels chúng ta sẽ tạo 1 hàm LoadMore Asycn Task. Chúng ta sẽ gọi function này để load thêm employee cho viewmodel khi ListView của chúng ta có item cuối cùng hiện lên.

 public async Task<bool> LoadMore()
        {
            Index++;
            var employeeService = new EmployeeServices();
            var newEmployees = new ObservableCollection<Employee>(await employeeService.GetEmplyees(Index, PageSize));
            EmployeeList = new ObservableCollection<Employee>(EmployeeList.Union(newEmployees).ToList());
            return newEmployees.Count == 0;
        }

Chúng ta sẽ cần thêm ai biến để lưu trữ Index và PageSize cho mỗi ViewModel

    ...
    public int Index
        {
            get
            {
                if (_index <= 0)
                    _index = 1;
                return _index;
            }

            set
            {

                _index = value;
            }
        }
        public int PageSize
        {
            get
            {
                if (_pageSize <= 0)
                    _pageSize = 1;
                return _pageSize;
            }
            set
            {
                _pageSize = value;
            }
        }
        ...
         public EmployeeViewModel()
        {
            Index = 1;
            PageSize = 5;
            InitializeDataAsync();
        }
        public EmployeeViewModel(INavigation navi)
        {
            Index = 1;
            PageSize = 5;
            InitializeDataAsync();
            _navi = navi;
        }
        ...

Ở đây bạn sẽ nghĩ đơn giản thế này, khi người dùng scroll list view thì các item được khởi tạo và hiện lên màn hình thì nó sẽ bật sự kiện OnItemAppearing. Trong sự kiện này chúng ta kiểm tra item xuất hiện có phải là item cuối cùng trong List Employee của mình hiện tại không. Nếu đúng thì chúng ta sẽ load thêm employee vào cho thằng ListEmployee của ViewModel. Bạn có thể thấy mình đang dùng ObservableCollection<T> thay thế cho List Object, đây là một cấu trúc dữ liệu chịu trách nhiệm cập nhật dữ liệu ra phía ngoài dữ liệu khi chúng ta "thêm,sửa, xóa" một phần tử nào đó trong tập dữ liệu. Và hầu như nó là kiểu dữ liệu bắt buộc dùng nếu chúng ta muốn nó tự cập nhật ngoài dao diện và List hay Ilist sẽ không hỗ trợ vấn đề này.

Bây giờ chúng ta cập nhật sự kiện để loadmore trong controller. Tại Employee.xaml chúng ta thêm sự kiện OnItemAppearing để tính toán và gọi loadMore của ViewModel.

Employee.xaml

  ...
  ItemAppearing="EmployeeListView_OnItemAppearing"
  ...

Employee.xaml.cs


 private async void EmployeeListView_OnItemAppearing(object sender, ItemVisibilityEventArgs e)
        {
            var employeeViewModel = BindingContext as EmployeeViewModel;
            if (employeeViewModel == null)
                return;
            if (employeeViewModel.IsLoading || employeeViewModel.EmployeeList.Count == 0)
            {
                return;
            }
            if (e.Item as Models.Employee == employeeViewModel.EmployeeList[employeeViewModel.EmployeeList.Count - 1] && !lastItem)
            {
                employeeViewModel.IsLoading = true;
                lastItem = await employeeViewModel.LoadMore();
                //employeeViewModel.IsLoading = false;
            }
        }

Chúng ta sử dụng sự kiện OnItemAppearing nó sẽ gọi mỗi khi item của list được xuất hiện trên màn hình, khi đấy sẽ kiểm tra item này có phải là item cuối của list employee trong view model hiện tại hay chưa và gọi loadmore để add thêm employee vào trong list.

Thế là xong. Chúc các bạn code vui vẻ.

Bên dưới là link các phần khác các bạn có thể tham khảo:

Part1: https://viblo.asia/RichardTran_NLong/posts/DzVkpoQKenW

Part2: https://viblo.asia/RichardTran_NLong/posts/PwRGgVqMvEd

Part3: https://viblo.asia/RichardTran_NLong/posts/PDOGqLdMvjx


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí