Building GNOME Apps with Rust, Part 6: Fetching Feeds
This article details integrating network fetching into a GNOME application without freezing the user interface. Previous steps established a sidebar displaying feed names, but selecting a feed only updated the display text, not its content. Attempting a direct network fetch within the feed-selected signal handler, as a naive solution, causes the entire application window to freeze for the duration of the fetch. This freeze occurs because GTK's main loop runs on a single thread, and blocking it prevents any UI updates or responsiveness.The core problem is that GTK/GObject types are not thread-safe, meaning they cannot be directly manipulated from background threads. The solution involves running two distinct executors: GTK's GLib main loop for UI tasks and a Tokio runtime for I/O-bound operations like network requests. These executors are kept strictly separate, adhering to a rule where the GLib loop never blocks, and Tokio never directly touches GTK/GObject types. The communication between them happens at a single "seam" where a future on the GLib context can await a result from Tokio, which then safely returns to the main context as a plain value.To implement this, the application adds Tokio and reqwest dependencies. The Tokio runtime is built once in main before the GTK application starts, and its handle is stored in the GazetteApplication struct. A new src/fetch.rs module is created containing an asynchronous fetch_feed function. This function uses reqwest within the Tokio runtime to download and parse RSS/Atom feeds, returning a Vec<FeedItem> struct. This FeedItem is a plain Rust struct, not a GObject, ensuring it can be safely passed back to the GLib main thread without violating thread-safety rules.
reqwestdependencies. The Tokio runtime is built once inmainbefore the GTK application starts, and its handle is stored in theGazetteApplicationstruct. A newsrc/fetch.rsmodule is created containing an asynchronousfetch_feedfunction. This function usesreqwestwithin the Tokio runtime to download and parse RSS/Atom feeds, returning aVec<FeedItem>struct. ThisFeedItemis a plain Rust struct, not a GObject, ensuring it can be safely passed back to the GLib main thread without violating thread-safety rules.