Diese Präsentation wurde erfolgreich gemeldet.
Die SlideShare-Präsentation wird heruntergeladen. ×

Rambler.iOS #6: Pagination Demystified

Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
PAGINATION
DEMYSTIFIED
Egor Tolstoy @igrekde

YouTube-Videos werden auf SlideShare nicht mehr unterstützt.

Original auf YouTube ansehen

DISCLAIMER
ВЫСТУПЛЕНИЕ ОСНОВАНО НА ЛИЧНОМ
СТРАДАНИЯХ ОПЫТЕ.
ДОКЛАД СОДЕРЖИТ ДЕТАЛЬНОЕ ОПИСАНИЕ
ОТВРАТИТЕЛЬНЫХ КОСТЫЛЕЙ
И П...
Nächste SlideShare
Selenium vs AJAX
Selenium vs AJAX
Wird geladen in …3
×

Hier ansehen

1 von 75 Anzeige

Rambler.iOS #6: Pagination Demystified

Herunterladen, um offline zu lesen

Егор Толстой рассказывает о том, как он справился с проблемами постраничной загрузки данных в мобильном клиенте для одного абстрактного известного блог-сервиса.

Rambler.iOS - митапы iOS-разработчиков, организуемые компанией RAMBLER&Co.

Егор Толстой рассказывает о том, как он справился с проблемами постраничной загрузки данных в мобильном клиенте для одного абстрактного известного блог-сервиса.

Rambler.iOS - митапы iOS-разработчиков, организуемые компанией RAMBLER&Co.

Anzeige
Anzeige

Weitere Verwandte Inhalte

Diashows für Sie (20)

Weitere von RAMBLER&Co (20)

Anzeige

Aktuellste (20)

Rambler.iOS #6: Pagination Demystified

  1. 1. PAGINATION DEMYSTIFIED Egor Tolstoy @igrekde
  2. 2. DISCLAIMER ВЫСТУПЛЕНИЕ ОСНОВАНО НА ЛИЧНОМ СТРАДАНИЯХ ОПЫТЕ. ДОКЛАД СОДЕРЖИТ ДЕТАЛЬНОЕ ОПИСАНИЕ ОТВРАТИТЕЛЬНЫХ КОСТЫЛЕЙ И ПОЭТОМУ НЕ РЕКОМЕНДУЕТСЯ К ПРОСМОТРУ НИКОМУ.
  3. 3. Локальная фильтрация Динамический размер страницы Пересобирается раз в час Выдача лежит на CDN Все еще limit/offset authorId = postId >> 32
  4. 4. Техники пагинации Как подступиться Загрузка вниз Обновление ленты
  5. 5. limit/offset httр://api.соm/entries?offset=100&limit=20
  6. 6. 0 1 2 cache server 0 1 2 3 4 5 6 7
  7. 7. 0 1 2 cache server 0 1 2 3 4 5 6 7 offset: 3 limit: 5 3 4 5 6 7
  8. 8. 0 1 2 cache server 0 1 2 3 4 5 6 7 offset: 3 limit: 5 3 4 5 6 7 3 4 5 6 7 3 4 5 6 7
  9. 9. Номера страниц httр://api.соm/entries?page_number=3
  10. 10. cache server 0 1 2 0
  11. 11. cache server 0 1 2 0 page: 1 1
  12. 12. cache server 0 1 2 0 page: 1 11 2 1
  13. 13. Позиции элементов не меняются Условия
  14. 14. Курсоры httр://api.соm/entries?since=752284800&limit=10 httр://api.соm/entries? max_id=228&limit=10 httр://api.соm/entries? after=MTAxNTE&limit=10
  15. 15. cache server 0 1 2 21:04- 21:02- 19:35- 19:18- 17:44- 16:02- 15:58- 15:49- 15:40- 3 4 5 6 7 8 0 1 2 19:35- 19:18- 17:44- 15:21- 9
  16. 16. cache server 0 1 2 21:04- 21:02- 19:35- 19:18- 17:44- 16:02- 15:58- 15:49- 15:40- 3 4 5 6 7 8 0 1 2 19:35- 19:18- 17:44- since: 17:44 limit: 5 15:21- 9 3 4 5 6 7 16:02- 15:58- 15:49- 15:40- 15:21-
  17. 17. cache server 0 1 2 21:04- 21:02- 19:35- 19:18- 17:44- 16:02- 15:58- 15:49- 15:40- 3 4 5 6 7 8 0 1 2 19:35- 19:18- 17:44- since: 17:44 limit: 5 15:21- 9 3 4 5 6 7 16:02- 15:58- 15:49- 15:40- 15:21- 16:02- 15:58- 15:49- 15:40- 5 6 7 8 15:21- 9
  18. 18. Уникальный параметр каждого элемента Сортировка выдачи не меняется Условия
  19. 19. Изменение количества элементов Актуальность выдачи Обновление контента • Лента статична • Новые элементы добавляются сверху • Любая часть выдачи может быть изменена • Выдача всегда актуальна • Выдача может быть переформирована • Отображаемые данные не обновляются • Отображаемые данные могут быть изменены
  20. 20. 1. Количество элементов не меняется 2. Выдача всегда актуальна 3. Данные могут быть изменены Афиша.Рестораны
  21. 21. 1. Новые элементы добавляются только сверху 2. Выдача всегда актуальна 3. Данные могут быть изменены Афиша
  22. 22. 1. Количество элементов не меняется 2. Выдача может быть переформирована 3. Данные не могут быть изменены Рамблер.Новости
  23. 23. 1. Любая часть выдачи может быть изменена 2. Выдача всегда актуальна 3. Данные могут быть изменены Рамблер.Почта
  24. 24. тем временем в офисе бэкенда
  25. 25. Решения проблем пагинации на клиенте
  26. 26. item 0 item 1 item 2 item 3 item 4 item 5 item 6 item 7 item 8 item 9 Загрузка вниз Случай 1: Лента статична 1/5
  27. 27. item 0 item 1 item 2 item 3 item 4 item 5 item 6 item 7 item 8 item 9 offset: 0 limit: 5 Загрузка вниз Случай 1: Лента статична 2/5
  28. 28. item 0 (cached) item 1 (cached) item 2 (cached) item 3 (cached) item 4 (cached) item 5 item 6 item 7 item 8 item 9 offset: 0 limit: 5 Загрузка вниз Случай 1: Лента статична 3/5
  29. 29. item 0 (cached) item 1 (cached) item 2 (cached) item 3 (cached) item 4 (cached) item 5 item 6 item 7 item 8 item 9 offset: 0 limit: 5 offset: 5 limit: 5 Загрузка вниз Случай 1: Лента статична 4/5
  30. 30. item 0 (cached) item 1 (cached) item 2 (cached) item 3 (cached) item 4 (cached) item 5 (cached) item 6 (cached) item 7 (cached) item 8 (cached) item 9 (cached) offset: 0 limit: 5 offset: 5 limit: 5 Загрузка вниз Случай 1: Лента статична 5/5
  31. 31. paging.startIndex = cachedPosts.count; paging.count = 5;
  32. 32. item 0 (cached) item 1 (cached) item 2 (cached) item 3 (cached) item 4 (cached) item 5 item 6 item 7 item 8 item 9 offset: 0 limit: 5 Загрузка вниз Случай 2: Добавились новые элементы 1/5
  33. 33. item 0 (cached) item 1 (cached) item 2 (cached) item 3 (cached) item 4 (cached) item 5 item 6 item 7 item 8 item 9 offset: 0 limit: 5 item 0' (new) item 2' (new) Загрузка вниз Случай 2: Добавились новые элементы 2/5
  34. 34. item 0 (cached) item 1 (cached) item 2 (cached) item 3 (cached) item 4 (cached) item 5 item 6 item 7 item 8 item 9 offset: 0 limit: 5 offset: 5 limit: 5 item 0' (new) item 2' (new) Загрузка вниз Случай 2: Добавились новые элементы 3/5
  35. 35. item 0 (cached) item 1 (cached) item 2 (cached) item 3 (cached) item 4 (cached) item 5 (cached) item 6 (cached) item 7 (cached) item 8 item 9 offset: 0 limit: 5 offset: 5 limit: 5 item 0' (new) item 2' (new) Загрузка вниз Случай 2: Добавились новые элементы 4/5
  36. 36. item 0 (cached) item 1 (cached) item 2 (cached) item 3 (cached) item 4 (cached) item 5 (cached) item 6 (cached) item 7 (cached) item 8 item 9 offset: 0 limit: 5 offset: 5 limit: 5 offset: 8 + 2 item 0' (new) item 2' (new) Загрузка вниз Случай 2: Добавились новые элементы 5/5
  37. 37. paging.startIndex = cachedPosts.count + intersections; paging.count = 5;
  38. 38. item 0 (cached) item 1 (cached) item 2 (cached) item 3 (cached) item 4 (cached) item 5 item 6 item 7 item 8 item 9 offset: 0 limit: 5 Загрузка вниз Случай 3: Удалены старые элементы 1/7
  39. 39. item 0 (cached) item 1 (cached) item 2 (cached) item 3 (cached) item 4 (cached) item 5 item 6 item 7 item 8 item 9 offset: 0 limit: 5 item 10 item 11 Загрузка вниз Случай 3: Удалены старые элементы 2/7
  40. 40. item 0 (cached) item 1 (cached) item 2 (cached) item 3 (cached) item 4 (cached) item 5 item 6 item 7 item 8 item 9 offset: 0 limit: 5 item 10 item 11 offset: 5 limit: 5 Загрузка вниз Случай 3: Удалены старые элементы 3/7
  41. 41. item 0 (cached) item 1 (cached) item 2 (cached) item 3 (cached) item 4 (cached) item 5 item 6 item 7 (cached) item 8 (cached) item 9 (cached) offset: 0 limit: 5 item 10 (cached) item 11 (cached) offset: 5 limit: 5 Загрузка вниз Случай 3: Удалены старые элементы 4/7
  42. 42. item 0 (cached) item 1 (cached) item 2 (cached) item 3 (cached) item 4 (cached) item 5 item 6 item 7 item 8 item 9 offset: 0 limit: 5 ... Загрузка вниз Случай 3: Удалены старые элементы 5/7
  43. 43. item 0 (cached) item 1 (cached) item 2 (cached) item 3 (cached) item 4 (cached) item 5 item 6 item 7 item 8 item 9 offset: 0 limit: 5 ... offset: 4 limit: 5 Загрузка вниз Случай 3: Удалены старые элементы 6/7
  44. 44. item 0 (cached) item 1 (cached) item 2 (cached) item 3 (cached) item 4 (cached) item 5 (cached) item 6 (cached) item 7 (cached) item 8 (cached) item 9 offset: 0 limit: 5 ... offset: 4 limit: 5 Загрузка вниз Случай 3: Удалены старые элементы 7/7
  45. 45. paging.startIndex = startIndex - 1; paging.count = 5;
  46. 46. еще одна шутка про Facebook
  47. 47. item 0 item 1 item 2 item 3 item 4 item 5 item 6 item 7 item 8 item 9 Загрузка вниз Случай 4: Порядок выдачи пересобирается 1/5
  48. 48. item 0 item 1 item 2 item 3 item 4 item 5 item 6 item 7 item 8 item 9 items: 0,1,2,3,4 Загрузка вниз Случай 4: Порядок выдачи пересобирается 2/5
  49. 49. item 0 (cached) item 1 (cached) item 2 (cached) item 3 (cached) item 4 (cached) item 5 item 6 item 7 item 8 item 9 items: 0,1,2,3,4 Загрузка вниз Случай 4: Порядок выдачи пересобирается 3/5
  50. 50. item 6 item 1 (cached) item 4 (cached) item 5 item 8 item 9 item 2 (cached) item 0 (cached) item 7 item 3 (cached) Загрузка вниз Случай 4: Порядок выдачи пересобирается 4/5
  51. 51. item 6 (cached) item 1 (cached) item 4 (cached) item 5 (cached) item 8 (cached) item 9 (cached) item 2 (cached) item 0 (cached) item 7 (cached) item 3 (cached) items: 5,6,7,8,9 Загрузка вниз Случай 4: Порядок выдачи пересобирается 5/5
  52. 52. NSRange pageRange = NSMakeRange(startIndex, 5); NSArray *postIds = [snapshot subarrayWithRange:pageRange];
  53. 53. item 0 (new) item 1 (new) item 2 (new) item 3 (new) item 4 (new) item 5 (new) item 7 (cached) item 8 (cached) item 9 (cached) item 6 (new) Обновление Случай 1: Появилось много новых элементов 1/3
  54. 54. item 7 (cached) item 8 (cached) item 9 (cached) offset: 0 limit: 5 item 0 (new) item 1 (new) item 2 (new) item 3 (new) item 4 (new) item 5 (new) item 6 (new) Обновление Случай 1: Появилось много новых элементов 2/3
  55. 55. item 0 (cached) item 1 (cached) item 2 (cached) item 3 (cached) item 4 (cached) item 5 (new) item 7 (cached) item 8 (cached) item 9 (cached) offset: 0 limit: 5 item 6 (new) Обновление Случай 1: Появилось много новых элементов 3/3
  56. 56. if (intersections == 0) { [self dropCache]; }
  57. 57. item 0 (cached) item 1 (cached) item 3 (cached) item 4 (cached) item 6 (cached) item 7 (cached) item 8 (deleted) item 9 (cached) item 5 (new) item 2 (new) Обновление Случай 2: Свободно изменяемая лента 1/1
  58. 58. for (ShortPost *post in diff) { [self updateCacheWith:post]; }
  59. 59. for (ShortPost *post in snapshot) { if (![cachedPosts containsObject:post]) { [self downloadPost:post]; } } for (Post *post in cachedPosts) { if (![snapshot containsObject:post]) { [self deletePost:post]; } }
  60. 60. item 6 item 1 (cached) item 4 (cached) item 5 item 8 item 9 item 2 (cached) item 0 (cached) item 7 item 3 (cached) Обновление Случай 3: Порядок выдачи пересобирается 1/1
  61. 61. NSString *lastModified = [self makeFeedHeadRequest]; if (![lastModified isEqual:cachedLastModified]) { [self dropCache]; [self obtainPostSnapshot]; [self obtainFirstPage]; }
  62. 62. item 0 (cached) item 1 (updated) item 2 (cached) item 3 (updated) item 4 (updated) item 5 item 6 item 7 item 8 item 9 Обновление Случай 4: Данные элементов меняются 1/1
  63. 63. for (NSUInteger i = 0; i < cachedPosts.count; i++) { Post *cachedPost = cachedPosts[i]; ShortPost *post = snapshot[i]; if (![cachedPost isEqual:post]) { [cachedPost updatePostWithShortPost:post]; } }
  64. 64. posts: NSArray <Post *> snapshot: NSArray <NSString *> offset: NSUInteger maxCount: NSUInteger lastModified: NSDate Feed
  65. 65. PostService loadPosts didLoad Cache
  66. 66. PostService loadPosts didLoad Cache
  67. 67. CacheTracker PostService loadPosts didLoad Cache
  68. 68. PagingFacade PostService ViewController FeedService CacheUpdater SnapshotProcessor PagingCalculator
  69. 69. @protocol PostPagingFacade <NSObject> - (void)loadNextPageWithBlock:(ErrorBlock)block; - (void)refreshCategoryWithBlock:(ErrorBlock)block; - (void)reloadCategoryWithBlock:(ErrorBlock)block; @end
  70. 70. Клиент должен быть простым
  71. 71. Техники пагинации Как подступиться Загрузка вниз Обновление ленты
  72. 72. Egor Tolstoy @igrekde не смог придумать заключительную фразу

×