rambler.ios #6 - pagination demystified

74
PAGINATION DEMYSTIFIED Egor Tolstoy @igrekde

Upload: rambler-ios

Post on 22-Jan-2017

267 views

Category:

Mobile


0 download

TRANSCRIPT

Page 1: Rambler.iOS #6 - Pagination Demystified

PAGINATION DEMYSTIFIED

Egor Tolstoy @igrekde

Page 2: Rambler.iOS #6 - Pagination Demystified

DISCLAIMER

ВЫСТУПЛЕНИЕ ОСНОВАНО НА ЛИЧНОМ СТРАДАНИЯХ ОПЫТЕ.

ДОКЛАД СОДЕРЖИТ ДЕТАЛЬНОЕ ОПИСАНИЕ ОТВРАТИТЕЛЬНЫХ КОСТЫЛЕЙ

И ПОЭТОМУ НЕ РЕКОМЕНДУЕТСЯ К ПРОСМОТРУ НИКОМУ.

Page 3: Rambler.iOS #6 - Pagination Demystified
Page 4: Rambler.iOS #6 - Pagination Demystified
Page 5: Rambler.iOS #6 - Pagination Demystified

Локальная фильтрация

Динамический размер страницы

Пересобирается раз в час

Выдача лежит на CDN

Все еще limit/offset

authorId = postId >> 32

Page 6: Rambler.iOS #6 - Pagination Demystified

Техники пагинации

Как подступиться

Загрузка вниз

Обновление ленты

Page 7: Rambler.iOS #6 - Pagination Demystified

limit/offset

httр://api.соm/entries?offset=100&limit=20

Page 8: Rambler.iOS #6 - Pagination Demystified

0

1

2

cache server

0

1

2

3

4

5

6

7

Page 9: Rambler.iOS #6 - Pagination Demystified

0

1

2

cache server

0

1

2

3

4

5

6

7

offset: 3 limit: 5

3

4

5

6

7

Page 10: Rambler.iOS #6 - Pagination Demystified

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

Page 11: Rambler.iOS #6 - Pagination Demystified

Номера страниц

httр://api.соm/entries?page_number=3

Page 12: Rambler.iOS #6 - Pagination Demystified

cache server

0

1

2

0

Page 13: Rambler.iOS #6 - Pagination Demystified

cache server

0

1

2

0

page: 1

1

Page 14: Rambler.iOS #6 - Pagination Demystified

cache server

0

1

2

0

page: 1

11

2

1

Page 15: Rambler.iOS #6 - Pagination Demystified

Позиции элементов не меняются

Условия

Page 16: Rambler.iOS #6 - Pagination Demystified

Курсоры

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

Page 17: Rambler.iOS #6 - Pagination Demystified

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

Page 18: Rambler.iOS #6 - Pagination Demystified

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-

Page 19: Rambler.iOS #6 - Pagination Demystified

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

Page 20: Rambler.iOS #6 - Pagination Demystified

Уникальный параметр каждого элемента

Сортировка выдачи не меняется

Условия

Page 21: Rambler.iOS #6 - Pagination Demystified

Изменение количества элементов

Актуальность выдачи

Обновление контента

• Лента статична • Новые элементы добавляются сверху

• Любая часть выдачи может быть изменена

• Выдача всегда актуальна

• Выдача может быть переформирована

• Отображаемые данные не обновляются

• Отображаемые данные могут быть изменены

Page 22: Rambler.iOS #6 - Pagination Demystified

1. Количество элементов не

меняется

2. Выдача всегда актуальна

3.Данные могут быть

изменены

Афиша.Рестораны

Page 23: Rambler.iOS #6 - Pagination Demystified

1. Новые элементы

добавляются только сверху

2. Выдача всегда актуальна

3. Данные могут быть

изменены

Афиша

Page 24: Rambler.iOS #6 - Pagination Demystified

1. Количество элементов не

меняется

2. Выдача может быть

переформирована

3.Данные не могут быть

изменены

Рамблер.Новости

Page 25: Rambler.iOS #6 - Pagination Demystified

1.Любая часть выдачи может

быть изменена

2. Выдача всегда актуальна

3.Данные могут быть

изменены

Рамблер.Почта

Page 26: Rambler.iOS #6 - Pagination Demystified

тем временем в офисе бэкенда

Page 27: Rambler.iOS #6 - Pagination Demystified

Решения проблем

пагинации на

клиенте

Page 28: Rambler.iOS #6 - Pagination Demystified

item 0

item 1

item 2

item 3

item 4

item 5

item 6

item 7

item 8

item 9

Загрузка вниз

Случай 1:

Лента статична

1/5

Page 29: Rambler.iOS #6 - Pagination Demystified

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

Page 30: Rambler.iOS #6 - Pagination Demystified

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

Page 31: Rambler.iOS #6 - Pagination Demystified

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

Page 32: Rambler.iOS #6 - Pagination Demystified

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

Page 33: Rambler.iOS #6 - Pagination Demystified

paging.startIndex = cachedPosts.count;

paging.count = 5;

Page 34: Rambler.iOS #6 - Pagination Demystified

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

Page 35: Rambler.iOS #6 - Pagination Demystified

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

Page 36: Rambler.iOS #6 - Pagination Demystified

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

Page 37: Rambler.iOS #6 - Pagination Demystified

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

Page 38: Rambler.iOS #6 - Pagination Demystified

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

Page 39: Rambler.iOS #6 - Pagination Demystified

paging.startIndex = cachedPosts.count

+ intersections; paging.count = 5;

Page 40: Rambler.iOS #6 - Pagination Demystified

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

Page 41: Rambler.iOS #6 - Pagination Demystified

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

Page 42: Rambler.iOS #6 - Pagination Demystified

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

Page 43: Rambler.iOS #6 - Pagination Demystified

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

Page 44: Rambler.iOS #6 - Pagination Demystified

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

Page 45: Rambler.iOS #6 - Pagination Demystified

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

Page 46: Rambler.iOS #6 - Pagination Demystified

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

Page 47: Rambler.iOS #6 - Pagination Demystified

paging.startIndex = startIndex - 1;

paging.count = 5;

Page 48: Rambler.iOS #6 - Pagination Demystified

еще одна шутка про Facebook

Page 49: Rambler.iOS #6 - Pagination Demystified

item 0

item 1

item 2

item 3

item 4

item 5

item 6

item 7

item 8

item 9

Загрузка вниз

Случай 4:

Порядок выдачи

пересобирается

1/5

Page 50: Rambler.iOS #6 - Pagination Demystified

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

Page 51: Rambler.iOS #6 - Pagination Demystified

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

Page 52: Rambler.iOS #6 - Pagination Demystified

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

Page 53: Rambler.iOS #6 - Pagination Demystified

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

Page 54: Rambler.iOS #6 - Pagination Demystified

NSRange pageRange = NSMakeRange(startIndex, 5);

NSArray *postIds = [snapshot

subarrayWithRange:pageRange];

Page 55: Rambler.iOS #6 - Pagination Demystified

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

Page 56: Rambler.iOS #6 - Pagination Demystified

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

Page 57: Rambler.iOS #6 - Pagination Demystified

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

Page 58: Rambler.iOS #6 - Pagination Demystified

if (intersections == 0) {

[self dropCache]; }

Page 59: Rambler.iOS #6 - Pagination Demystified

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

Page 60: Rambler.iOS #6 - Pagination Demystified

for (ShortPost *post in diff) {

[self updateCacheWith:post]; }

Page 61: Rambler.iOS #6 - Pagination Demystified

for (ShortPost *post in snapshot) {

if (![cachedPosts containsObject:post]) {

[self downloadPost:post];

}

}

for (Post *post in cachedPosts) {

if (![snapshot containsObject:post]) {

[self deletePost:post];

}

}

Page 62: Rambler.iOS #6 - Pagination Demystified

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

Page 63: Rambler.iOS #6 - Pagination Demystified

NSString *lastModified = [self makeFeedHeadRequest];

if (![lastModified isEqual:cachedLastModified]) { [self dropCache]; [self obtainPostSnapshot]; [self obtainFirstPage]; }

Page 64: Rambler.iOS #6 - Pagination Demystified

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

Page 65: Rambler.iOS #6 - Pagination Demystified

for (NSUInteger i = 0; i < cachedPosts.count; i++) {

Post *cachedPost = cachedPosts[i];

ShortPost *post = snapshot[i];

if (![cachedPost isEqual:post]) {

[cachedPost updatePostWithShortPost:post];

}

}

Page 66: Rambler.iOS #6 - Pagination Demystified

posts: NSArray <Post *>

snapshot: NSArray <NSString *>

offset: NSUInteger

maxCount: NSUInteger

lastModified: NSDate

Feed

Page 67: Rambler.iOS #6 - Pagination Demystified

PostServiceloadPosts

didLoad

Cache

Page 68: Rambler.iOS #6 - Pagination Demystified

PostServiceloadPosts

didLoad

Cache

Page 69: Rambler.iOS #6 - Pagination Demystified

CacheTracker

PostServiceloadPosts

didLoad

Cache

Page 70: Rambler.iOS #6 - Pagination Demystified

PagingFacade

PostService

ViewController

FeedService CacheUpdater

SnapshotProcessor

PagingCalculator

Page 71: Rambler.iOS #6 - Pagination Demystified

@protocol PostPagingFacade <NSObject>

- (void)loadNextPageWithBlock:(ErrorBlock)block;

- (void)refreshCategoryWithBlock:(ErrorBlock)block;

- (void)reloadCategoryWithBlock:(ErrorBlock)block;

@end

Page 72: Rambler.iOS #6 - Pagination Demystified

Клиент должен быть

простым

Page 73: Rambler.iOS #6 - Pagination Demystified

Техники пагинации

Как подступиться

Загрузка вниз

Обновление ленты

Page 74: Rambler.iOS #6 - Pagination Demystified

Egor Tolstoy @igrekde

не смог придумать заключительную фразу