Skip to main content

t_request_runner 1.0.0 copy "t_request_runner: ^1.0.0" to clipboard
t_request_runner: ^1.0.0 copied to clipboard

A powerful, architecture-ready DataState wrapper and ultra-responsive RequestRunner mixin for GetX with built-in optimistic UI updates.

TRequestRunner 🚀 #

A highly optimized, Clean Architecture-ready DataState wrapper and ultra-responsive RequestRunner mixin for GetX. Seamlessly manage API network states, encapsulate Dio responses, and execute advanced Optimistic UI Updates with zero boilerplate.

The Philosophy & The GetX Dilemma 🧠 #

For GetX lovers, reactive power and lightweight execution are unmatched. However, GetX introduces a major architectural dilemma when dealing with asynchronous API requests: State Mutation Chaos.

Developers constantly find themselves duplicating tedious boilerplates inside every single controller method:

// ❌ The Repetitive GetX Dilemma
status = RequestStatus.loading;
update();
try {
  final res = await api.getData();
  status = RequestStatus.success;
  update();
} catch(e) {
  status = RequestStatus.error;
  update();
}
This repetitive cycle clutters controllers and makes tracking UI update() triggers a complete nightmare.

TRequestRunner bridges this gap by injecting an embedded state emission system (inspired by BLoC's strict emit(State) discipline) directly into your GetxController. By passing your network Future to the runner, it internally intercepts the lifecycle, handles the safe transition between states, and dispatches the reactive update() triggers underneath. You write the logic once; the runner handles the emission boilerplate forever.

🔮 The Premium onOptimistic Power
Beyond standard state management, TRequestRunner natively supports Optimistic UI Updates. Instead of forcing users to wait for network latency, you can instantly mutate the local UI state using onOptimistic. If the remote server request fails, the runner intelligently captures the failure and automatically triggers onRevert to seamlessly roll back the UI, offering a premium, lag-free user experience identical to world-class tech applications.

Key Features 💎
🛡️ Type-Safe DataState (src/data_state.dart): Implements Dart 3 sealed classes (DataSuccess and DataFailed) to guarantee robust, compile-time type safety for remote API responses.

⚡ Anti-Boilerplate State Emission (src/request_status.dart): Eliminates the dreaded repetitive state mutation and update() lines for UI loading/error states by 90%.

🔮 Advanced Optimistic UI Updates: Built-in declarative hooks (onOptimistic, onRevert, onCommit) to build hyper-fast, instantly responsive user experiences with bulletproof automated rollback mechanisms.

Folder Structure 📂
The package is strictly modularized for clean separation of concerns:

Plaintext
lib/
├── src/
│   ├── data_state.dart          # Sealed class wrappers for API responses
│   ├── request_status.dart      # UI state lifecycle enums
│   └── request_runner_mixin.dart# The core RequestRunner implementation
└── t_request_runner.dart        # Unified export gateway
Detailed Usage Example 💻
1. The Data Layer (Repository)
Return your network data wrapped safely inside a DataState:

Dart
import 'package:dio/dio.dart';
import 'package:t_request_runner/t_request_runner.dart';

class UserRepository {
  final Dio _dio = Dio();

  Future<DataState<List<User>>> getUsers() async {
    try {
      final response = await _dio.get('[https://api.example.com/users](https://api.example.com/users)');
      final data = (response.data as List).map((e) => User.fromJson(e)).toList();
      return DataSuccess(data);
    } on DioException catch (e) {
      return DataFailed(e.response, message: e.message ?? "Failed to fetch users");
    }
  }
}
2. The Logic Layer (Controller)
Apply the RequestRunner mixin. Look how clean and free from repetitive state mutations it becomes:

Dart
import 'package:get/get.dart';
import 'package:t_request_runner/t_request_runner.dart';

class UserController extends GetxController with RequestRunner {
  final UserRepository _repo = UserRepository();
  
  // Track state for UI rendering
  RequestStatus status = RequestStatus.idle;
  List<User> users = [];

  Future<void> fetchUsers() async {
    // ✅ No manual loading/error switching, no repetitive update() calls!
    await runRequest<List<User>>(
      future: _repo.getUsers(),
      setStatus: (s) => status = s, // Automatically emits status updates smoothly
      onSuccess: (data) => users = data,
      onError: (err) => print('Error logged: ${err.message}'),
    );
  }

  // Example of Premium Optimistic UI Update (e.g., Liking a user profile)
  Future<void> toggleLikeUser(int userId, bool currentStatus) async {
    await runRequest<bool>(
      future: _repo.likeUserOnServer(userId),
      setStatus: (s) {}, // Skip default loaders for smooth background execution
      onSuccess: (success) {},
      optimistic: true,
      onOptimistic: () => users.firstWhere((u) => u.id == userId).isLiked = !currentStatus, // Instantly update UI
      onRevert: () => users.firstWhere((u) => u.id == userId).isLiked = currentStatus,       // Rollback on server failure
    );
  }
}
5
likes
150
points
8
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A powerful, architecture-ready DataState wrapper and ultra-responsive RequestRunner mixin for GetX with built-in optimistic UI updates.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

dio, flutter, get

More

Packages that depend on t_request_runner