This is my main
import 'package:flutter/material.dart';
import 'package:gestionchamp/screen_intro/view/onboarding_screen.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'auth/main_page.dart';
import 'pages/login_page.dart';
import 'package:firebase_core/firebase_core.dart';
bool show = true;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
final prefs = await SharedPreferences.getInstance();
show = prefs.getBool('ON_BOARDING') ?? true;
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
textTheme: const TextTheme(
headline1: TextStyle(
fontSize: 25,
color: Colors.green,
fontWeight: FontWeight.bold,
),
headline2: TextStyle(
fontSize: 18,
color: Colors.green,
fontWeight: FontWeight.w400,
wordSpacing: 1.2,
height: 1.2),
headline3: TextStyle(
fontSize: 18,
color: Colors.green,
fontWeight: FontWeight.bold,
),
headline4: TextStyle(
fontSize: 18,
color: Colors.white,
fontWeight: FontWeight.bold,
),
)),
home: show ? OnBoardingScreen() : const MainPage(),
);
}
}
The mainPage
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import '../pages/home_page.dart';
import '../pages/login_page.dart';
import 'auth_page.dart';
class MainPage extends StatelessWidget {
const MainPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return HomePage();
} else {
return AuthPage();
}
},
),
);
}
}
and this is the Home page
import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:provider/provider.dart';
import 'package:gestionchamp/mqtt/MQTTAppState.dart';
import 'package:gestionchamp/mqtt/MQTTManager.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final TextEditingController _hostTextController = TextEditingController();
final TextEditingController _messageTextController = TextEditingController();
final TextEditingController _topicTextController = TextEditingController();
late MQTTAppState currentAppState;
late MQTTManager manager;
@override
void initState() {
super.initState();
/*
_hostTextController.addListener(_printLatestValue);
_messageTextController.addListener(_printLatestValue);
_topicTextController.addListener(_printLatestValue);
*/
}
@override
void dispose() {
_hostTextController.dispose();
_messageTextController.dispose();
_topicTextController.dispose();
super.dispose();
}
final user = FirebaseAuth.instance.currentUser!;
// document IDs
List<String> docIDs = [];
//get docIDs
Future getDocId() async {
await FirebaseFirestore.instance.collection('users').get().then(
(snapshot) => snapshot.docs.forEach(
(document) {
print(document.reference);
docIDs.add(document.reference.id);
},
),
);
}
@override
Widget build(BuildContext context) {
final MQTTAppState appState = Provider.of<MQTTAppState>(context);
// Keep a reference to the app state.
currentAppState = appState;
final Scaffold scaffold = Scaffold(body: _buildColumn());
return scaffold;
}
Widget _buildAppBar(BuildContext context) {
return AppBar(
title: const Text('MQTT'),
backgroundColor: Colors.greenAccent,
);
}
Widget _buildColumn() {
return Column(
children: <Widget>[
_buildConnectionStateText(
_prepareStateMessageFrom(currentAppState.getAppConnectionState)),
_buildEditableColumn(),
_buildScrollableTextWith(currentAppState.getHistoryText)
],
);
}
Widget _buildEditableColumn() {
return Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
_buildTextFieldWith(
_hostTextController,
'Entrez l\'adresse du broker',
currentAppState.getAppConnectionState),
const SizedBox(height: 10),
_buildTextFieldWith(
_topicTextController,
'Entrez un topic pour souscrire ou mettre en écoute',
currentAppState.getAppConnectionState),
const SizedBox(height: 10),
_buildPublishMessageRow(),
const SizedBox(height: 10),
_buildConnecteButtonFrom(currentAppState.getAppConnectionState)
],
),
);
}
Widget _buildPublishMessageRow() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
child: _buildTextFieldWith(_messageTextController,
'Entrez un message', currentAppState.getAppConnectionState),
),
_buildSendButtonFrom(currentAppState.getAppConnectionState)
],
);
}
Widget _buildConnectionStateText(String status) {
return Row(
children: <Widget>[
Expanded(
child: Container(
color: Colors.deepOrangeAccent,
child: Text(status, textAlign: TextAlign.center)),
),
],
);
}
Widget _buildTextFieldWith(TextEditingController controller, String hintText,
MQTTAppConnectionState state) {
bool shouldEnable = false;
if (controller == _messageTextController &&
state == MQTTAppConnectionState.connected) {
shouldEnable = true;
} else if ((controller == _hostTextController &&
state == MQTTAppConnectionState.disconnected) ||
(controller == _topicTextController &&
state == MQTTAppConnectionState.disconnected)) {
shouldEnable = true;
}
return TextField(
enabled: shouldEnable,
controller: controller,
decoration: InputDecoration(
contentPadding:
const EdgeInsets.only(left: 0, bottom: 0, top: 0, right: 0),
labelText: hintText,
));
}
Widget _buildScrollableTextWith(String text) {
return Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
width: 400,
height: 200,
child: SingleChildScrollView(
child: Text(text),
),
),
);
}
Widget _buildConnecteButtonFrom(MQTTAppConnectionState state) {
return Row(
children: <Widget>[
Expanded(
// ignore: deprecated_member_use
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.lightBlueAccent),
child: const Text('Connect'),
onPressed: state == MQTTAppConnectionState.disconnected
? _configureAndConnect
: null, //
),
),
const SizedBox(width: 10),
Expanded(
// ignore: deprecated_member_use
child: ElevatedButton(
style: ElevatedButton.styleFrom(backgroundColor: Colors.redAccent),
child: const Text('Disconnect'),
onPressed: state == MQTTAppConnectionState.connected
? _disconnect
: null, //
),
),
],
);
}
Widget _buildSendButtonFrom(MQTTAppConnectionState state) {
// ignore: deprecated_member_use
return ElevatedButton(
style: ElevatedButton.styleFrom(backgroundColor: Colors.green),
child: const Text('Send'),
onPressed: state == MQTTAppConnectionState.connected
? () {
_publishMessage(_messageTextController.text);
}
: null, //
);
}
// Fonctions utiles
String _prepareStateMessageFrom(MQTTAppConnectionState state) {
switch (state) {
case MQTTAppConnectionState.connected:
return 'Connected';
case MQTTAppConnectionState.connecting:
return 'Connecting';
case MQTTAppConnectionState.disconnected:
return 'Disconnected';
}
}
void _configureAndConnect() {
// ignore: flutter_style_todos
// TODO: Use UUID
String osPrefix = 'IoT';
if (Platform.isAndroid) {
osPrefix = 'Android ';
}
MQTTManager manager = MQTTManager(
host: _hostTextController.text,
topic: _topicTextController.text,
identifier: osPrefix,
state: currentAppState);
manager.initializeMQTTClient();
manager.connect();
}
void _disconnect() {
manager.disconnect();
}
void _publishMessage(String text) {
String osPrefix = 'IoT';
if (Platform.isAndroid) {
osPrefix = 'Android';
}
final String message = osPrefix ' a dit: ' text;
manager.publish(message);
_messageTextController.clear();
}
}
and this is the debug output
Error: Could not find the correct Provider<MQTTAppState> above this HomePage Widget
This happens because you used a `BuildContext` that does not include the provider
of your choice. There are a few common scenarios:
- You added a new provider in your `main.dart` and performed a hot-reload.
To fix, perform a hot-restart.
- The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then
other routes will not be able to access that provider.
- You used a `BuildContext` that is an ancestor of the provider you are trying to read.
Make sure that HomePage is under your MultiProvider/Provider<MQTTAppState>.
This usually happens when you are creating a provider and trying to read it immediately.
CodePudding user response:
The provider you're trying to call isn't identified at the place you're referring it. For this you need to provide it in the root widget or above the widget tree where you want to call it. You could wrap your MaterialApp by that provider like this:
Provider< MQTTAppState>(
create: (_) => MQTTAppState(),
child: MaterialApp(),
),
And please change the title of the post to the one that describes your problem.
CodePudding user response:
You have to put the provider somewhere in the widget tree, higher up than where you want to use it. I'm using a MultiProvider with which you can put several providers, but just one is also fine!
Something like this:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:my_app/screens/welcome_screen.dart';
import 'provider_updates.dart'; // The location of the MyFirstProvider class
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
print('Building $runtimeType');
MyFirstProvider myFirstProvider = MyFirstProvider(); // Create your provider here!
return MultiProvider(
providers: [
ChangeNotifierProvider<MyFirstProvider>(
create: (context) => myFirstProvider), // Use it here. Now, it will exist in the entire app!
// You can put more providers here
],
builder: (context, child) {
return MaterialApp(
home: WelcomeScreen(myThemeClass),
);
});
}
}