Combine checkInternet with retry.unlimited for persistent loading of critical data until connection returns
This skill combines checkInternet with retry.unlimited for persistent loading of critical data.
Creates a pattern that:
Perfect for:
import 'package:bloc_superpowers/bloc_superpowers.dart';
class AppCubit extends Cubit<AppState> {
AppCubit() : super(const AppState());
void loadInitialData() => mix(
key: this,
checkInternet: checkInternet,
retry: retry.unlimited,
() async {
final config = await api.getAppConfig();
final user = await api.getCurrentUser();
emit(state.copyWith(config: config, user: user));
},
);
}
Control how frequently it rechecks:
void loadInitialData() => mix(
key: this,
checkInternet: checkInternet(maxRetryDelay: 1.sec),
retry: retry.unlimited(maxDelay: 5.sec),
() async {
final config = await api.getAppConfig();
emit(state.copyWith(config: config));
},
);
App starts
↓
Check internet → No internet
↓
Wait 1 second, retry
↓
Check internet → No internet
↓
Wait 2 seconds, retry (exponential backoff)
↓
Check internet → No internet
↓
Wait 4 seconds, retry
↓
... keeps trying ...
↓
Check internet → Has internet!
↓
Execute API call
↓
Success! Data loaded
For critical data that needs to load ASAP:
void loadCriticalData() => mix(
key: this,
checkInternet: checkInternet(maxRetryDelay: 500.millis),
retry: retry.unlimited(
initialDelay: 500.millis,
maxDelay: 2.sec,
),
() async {
final data = await api.getCriticalData();
emit(data);
},
);
For less critical data:
void loadOptionalData() => mix(
key: this,
checkInternet: checkInternet(maxRetryDelay: 5.sec),
retry: retry.unlimited(
initialDelay: 2.sec,
maxDelay: 30.sec,
),
() async {
final data = await api.getOptionalData();
emit(state.copyWith(optionalData: data));
},
);
Show loading state while waiting for internet:
class SplashScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (context.isWaiting(AppCubit)) {
return const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(height: 16),
Text('Waiting for connection...'),
],
),
);
}
if (context.isFailed(AppCubit)) {
// This shouldn't happen with unlimited retry,
// but handle just in case
return const Center(child: Text('Error loading'));
}
// Data loaded, navigate away
return const HomeScreen();
}
}
// Cubit
class AppCubit extends Cubit<AppState> {
AppCubit() : super(const AppState());
void init() => mix(
key: this,
checkInternet: checkInternet(maxRetryDelay: 1.sec),
retry: retry.unlimited(maxDelay: 10.sec),
() async {
// Load all critical startup data
final config = await api.getConfig();
final user = await api.getCurrentUser();
final features = await api.getFeatureFlags();
emit(state.copyWith(
config: config,
user: user,
features: features,
isInitialized: true,
));
},
);
}
// Main
void main() {
runApp(
Superpowers(
child: BlocProvider(
create: (_) => AppCubit()..init(), // Start loading immediately
child: const MyApp(),
),
),
);
}
// Splash Screen
class SplashScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final state = context.watch<AppCubit>().state;
if (state.isInitialized) {
// Navigate to home when loaded
WidgetsBinding.instance.addPostFrameCallback((_) {
Navigator.pushReplacementNamed(context, '/home');
});
}
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const FlutterLogo(size: 100),
const SizedBox(height: 32),
if (context.isWaiting(AppCubit)) ...[
const CircularProgressIndicator(),
const SizedBox(height: 16),
const Text('Loading...'),
],
],
),
),
);
}
}
Create a reusable configuration:
// Config
const criticalLoadConfig = MixConfig(
checkInternet: checkInternet(maxRetryDelay: 1.sec),
retry: retry.unlimited(maxDelay: 10.sec),
);
// Usage
void loadData() => mix(
key: this,
config: criticalLoadConfig,
() async { ... },
);
// Or as a preset
const criticalLoad = MixPreset(
checkInternet: checkInternet(maxRetryDelay: 1.sec),
retry: retry.unlimited(maxDelay: 10.sec),
);
// Usage
void loadData() => criticalLoad(
key: this,
() async { ... },
);
npx skills add marcglasberg/retry-until-internet下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer