Skip to content

Instantly share code, notes, and snippets.

@ulisseshen
Created March 5, 2025 14:50
Show Gist options
  • Save ulisseshen/db82768bccb532b04ce6a83e7619e136 to your computer and use it in GitHub Desktop.
Save ulisseshen/db82768bccb532b04ce6a83e7619e136 to your computer and use it in GitHub Desktop.
POC necessário para mostrar o erro [ Null check operator used on a null value] que só aparece em RELEASE
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:async';
void main() {
// Initialize our error logger before running the app.
ErrorLogger.initialize();
runApp(MyApp());
}
class ErrorLogger {
// Using a ValueNotifier to update the UI whenever the log changes.
static final ValueNotifier<String> logNotifier = ValueNotifier<String>('');
static void initialize() {
FlutterError.onError = (FlutterErrorDetails details) {
// Also append the error to your custom log.
ErrorLogger.logNotifier.value +=
"\n-------------\n" + details.toString() + "\n";
};
// Pass all uncaught asynchronous errors that aren't handled by the Flutter framework to Crashlytics.
PlatformDispatcher.instance.onError = (error, stack) {
// Also append the error and stack trace to your custom log.
ErrorLogger.logNotifier.value += "\n-------------\nError: $error\nStack: $stack\n";
return true;
};
}
}
class CallbackManager {
CallbackManager._();
static final CallbackManager instance = CallbackManager._();
/// Registered callback that can be triggered externally.
VoidCallback? onCallback;
/// Method to trigger the callback if it is registered.
void triggerCallback() {
if (onCallback != null) {
onCallback!();
}
}
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test Callback with Navigation',
initialRoute: '/',
routes: {
'/': (context) => const HomeScreen(),
'/dummy': (context) => const DummyScreen(),
},
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home - CallbackWidget'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
const SizedBox(height: 20),
// Button to trigger the callback.
ElevatedButton(
onPressed: () {
CallbackManager.instance.triggerCallback();
},
child: const Text('Trigger Callback'),
),
const SizedBox(height: 20),
// Button to navigate to another screen.
ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/dummy');
},
child: const Text('Navigate to another screen'),
),
const SizedBox(height: 20),
const Text(
'Flutter Error Log:',
style: TextStyle(fontWeight: FontWeight.bold),
),
// The "textarea" displaying errors.
Expanded(
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
),
width: double.infinity,
padding: const EdgeInsets.all(8.0),
child: ValueListenableBuilder<String>(
valueListenable: ErrorLogger.logNotifier,
builder: (context, log, child) {
return SingleChildScrollView(
child: Text(
log,
style: const TextStyle(fontSize: 12, color: Colors.red),
),
);
},
),
),
),
],
),
),
);
}
}
class DummyScreen extends StatefulWidget {
const DummyScreen({super.key});
@override
State<DummyScreen> createState() => _DummyScreenState();
}
class _DummyScreenState extends State<DummyScreen> {
bool _callbackFired = false;
@override
void initState() {
super.initState();
// Register a callback that intentionally causes an error by calling setState after dispose.
CallbackManager.instance.onCallback = () {
Timer(const Duration(seconds: 1), () {
// This will trigger an error if the widget has been disposed.
setState(() {
_callbackFired = true;
});
});
};
}
@override
void dispose() {
// Clear the callback to avoid potential errors.
// CallbackManager.instance.onCallback = null;
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Dummy Screen'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
const Text(
'This is a dummy screen.\nThe CallbackWidget has been disposed.',
style: TextStyle(fontSize: 20),
textAlign: TextAlign.center,
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Go Back'),
),
],
),
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment