DEV Community на русском
Подписаться
Создание приложений GNOME на Rust, часть 6: получение лент
В этой статье подробно описывается интеграция сетевой выборки в приложение GNOME без замораживания пользовательского интерфейса. В предыдущих шагах была создана боковая панель с отображением названий ленты, но при выборе ленты обновлялся только текст отображения, а не его содержимое. Попытка прямой сетевой сборки в обработчике сигнала, выбранном по потоку, как наивное решение, приводит к зависновению всего окна приложения на время выборки. Это зависание происходит потому, что основной цикл GTK работает на одном потоке, и его блокировка препятствует обновлению интерфейса или отзывчивости.Основная проблема в том, что типы GTK/GObject не безопасны для потоков, то есть ими нельзя напрямую управлять из фоновых потоков. Решение предполагает запуск двух отдельных исполнителей: основного цикла GLib для задач UI от GTK и Tokio runtime для операций, связанных с вводом/выводом, таких как сетевые запросы. Эти экзекуторы строго раздельны, соблюдая правило, согласно которому петля GLib никогда не блокируется, и Tokio напрямую не касается типов GTK/GObject. Коммуникация между ними происходит на одном «шве», где будущее в контексте GLib может ожидать результата от Tokio, который затем безопасно возвращается в основной контекст в виде обычного значения.Для реализации этого приложение добавляет зависимости Tokio и 'reqwest'. Время выполнения Tokio создаётся один раз в 'main' перед запуском приложения GTK, а его дескриптор хранится в структуре 'GazetteApplication'. Создаётся новый модуль 'src/fetch.rs', содержащий асинхронную функцию 'fetch_feed'. Эта функция использует 'reqwest' в среде выполнения Tokio для загрузки и разбора RSS/Atom-потоков, возвращая структуру 'Vec<FeedItem>'. Этот «FeedItem» — это обычная структура Rust, а не GObject, что гарантирует безопасную передачу в основной поток GLib без нарушения правил безопасности потоков.