Irbisa · Шпаргалка
Live coding на Dart
Debounce, Result-типы, LRU-кэш, backoff, ограничение параллелизма, trie, трансформеры
Лайвкодинг: напишите переиспользуемую основную кнопку с текстом, колбэком
onPressedи состоянием загрузки. Как выглядит хорошая реализация?class PrimaryButton extends StatelessWidget { const PrimaryButton({ super.key, required this.label, required this.onPressed, this.loading = false,…Лайвкодинг: напишите виджет, который показывает текущее время и обновляется каждую секунду. Как сделать его точным и без утечек?
class Clock extends StatefulWidget { const Clock({super.key}); @override State<Clock> createState() => _ClockState();}…Этот виджет должен показывать введённый текст в
Textпод полем, ноTextостаётся пустым: что не так и как это исправить?class Echo extends StatelessWidget { const Echo({super.key}); @override Widget build(BuildContext context) { final controller = TextEditingController(); var typed = ''; return Column(children: [ TextField(controller: controller, onChanged: (v) => typed = v), Text(typed), ]); }}Пользователи жалуются, что не могут зарегистрироваться с адресами, которые работают везде: что не так с этим валидатором email и что выпустить вместо него?
final _email = RegExp(r'^[a-zA-Z0-9.]+@[a-zA-Z]+\.[a-zA-Z]{2,3}$'); String? validateEmail(String? value) { if (_email.hasMatch(value!)) return null; return 'Enter a valid email';}Лайвкодинг: распарсите JSON-строку с массивом товаров в
List<Product>и обратно. Как написатьfromJsonиtoJsonвручную?import 'dart:convert'; class Product { const Product({required this.id, required this.title, required this.price, this.note}); final int id;…Лайвкодинг: соберите экран TODO-списка с добавлением, отметкой и удалением. Как вы его построите за отведённое время?
class Todo { const Todo(this.id, this.title, {this.done = false}); final String id, title; final bool done; Todo copyWith({bool? done}) => Todo(id, title, done: done ?? this.done);}…Найдите баг: часть пользователей жалуется, что кнопка «Сохранить» (Save) крутится бесконечно, и помогает только повторное открытие экрана.
bool _saving = false; Future<void> _save() async { setState(() => _saving = true); await widget.repo.saveName(_name.text); if (!mounted) return; setState(() => _saving = false); Navigator.of(context).pop();} @overrideWidget build(BuildContext context) => PrimaryButton(label: 'Save', loading: _saving, onPressed: _save);API отдаёт плоский список транзакций, а дизайн хочет их под заголовками дат: как сгруппировать и чем вас подставит ключ типа
DateTime?DateTime dayOf(DateTime t) { final local = t.toLocal(); // the server sends UTC return DateTime(local.year, local.month, local.day); // time stripped} List<({DateTime day, List<Txn> items})> sections(List<Txn> txns) {…Поле поиска шлёт запрос на каждое нажатие, а rxdart добавить нельзя: как написать debounce и throttle и какой из них теряет последнее нажатие?
class Debouncer { Debouncer(this.delay); final Duration delay; Timer? _timer; void run(void Function() action) {…Каждый вызывающий оборачивает репозиторий в try/catch, и половина про это забывает: как написать
Result<T, E>сmap,mapErrorиfoldвзамен?sealed class Result<T, E> { const Result(); R fold<R>(R Function(T value) onOk, R Function(E error) onErr) => switch (this) { Ok(:final value) => onOk(value), Err(:final error) => onErr(error),…Эта мемоизированная функция цены должна пропускать вычисление на 40 мс, но быстрее не становится, а мапа всё растёт: почему кэш ни разу не срабатывает?
final _cache = <List<Object>, double>{}; double shippingCost(String zone, double kg) { final key = [zone, kg]; final hit = _cache[key]; if (hit != null) return hit; return _cache[key] = _computeShipping(zone, kg); // 40 ms}Напишите кэш в памяти, записи которого истекают по TTL: где проверять истечение и что не даёт ему расти бесконечно?
import 'package:clock/clock.dart'; class TtlCache<K, V> { TtlCache({required this.ttl, this.maxEntries = 200}); final Duration ttl;…Найдите баг: с этим
LruCacheперед загрузчиком аватаров только что изменённый пользователем аватар часто вытесняется следующим.class LruCache<K, V extends Object> { LruCache(this.capacity); final int capacity; final _map = <K, V>{}; // insertion order: first key = least recent V? get(K key) { final value = _map.remove(key); if (value != null) _map[key] = value; // move to the end: most recent return value; } void put(K key, V value) { _map[key] = value; if (_map.length > capacity) _map.remove(_map.keys.first); }}В кэше лежат сообщения, отсортированные по времени, и сервер присылает ещё одну отсортированную страницу: как слить их и выкинуть дубли по id за один проход?
List<Message> mergeSorted(List<Message> cached, List<Message> fresh) { final out = <Message>[]; final seen = <String>{}; var i = 0, j = 0; void take(Message m) {…Ветка комментариев приходит вложенным деревом, а
ListView.builderнужен плоский список с отступами: как развернуть дерево без рекурсии?class Comment { Comment(this.id, this.text, {this.children = const []}); final String id; final String text; final List<Comment> children;}…Напишите типизированную шину событий с подпиской и отпиской: что удерживает слушателя живым после того, как зарегистрировавший его экран уничтожен?
class EventBus { final _ctrl = StreamController<Object>.broadcast(); void emit(Object event) => _ctrl.add(event); // where + cast: dart:async has no whereType on Stream…Напишите функцию, которая глубоко сравнивает два раскодированных JSON-значения и возвращает путь первого расхождения вместо bool: в чём ловушки?
String? firstDiff(Object? expected, Object? actual, [String path = r'$']) { if (expected is Map && actual is Map) { final keys = <Object?>{...expected.keys, ...actual.keys}.toList() ..sort((a, b) => '$a'.compareTo('$b')); // insertion order would make "first" random for (final k in keys) { if (!expected.containsKey(k)) return '$path.$k: unexpected (${actual[k]})';…Напишите лимитер, который пускает не больше пяти загрузок в скользящую минуту, а остальные ставит в очередь: почему счётчик, сбрасываемый раз в минуту, неверный ответ?
import 'package:clock/clock.dart'; class RateLimiter { RateLimiter({required this.max, required this.window}); final int max;…Поток GPS отдаёт десять точек в секунду: как написать трансформер, который отдаёт не чаще одной точки в пять секунд и пропускает точки ближе десяти метров к последней оставленной?
class Fix { const Fix(this.lat, this.lon, this.at); final double lat, lon; final DateTime at; // the fix's own timestamp, not DateTime.now()}…