My code works fine last week, then when the credentials expire, i recreate another credentials and replace the credentials, now the code doesnt work anymore and show the error
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: LateInitializationError: Field 'dialogflow' has not been initialized.
import 'package:dialogflow_grpc/dialogflow_grpc.dart';
import 'package:dialogflow_grpc/generated/google/cloud/dialogflow/v2beta1/session.pb.dart';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class Chat extends StatefulWidget {
Chat({Key? key}) : super(key: key);
@override
_ChatState createState() => _ChatState();
}
class _ChatState extends State<Chat> {
final List<ChatMessage> _messages = <ChatMessage>[];
final TextEditingController _textController = TextEditingController();
late DialogflowGrpcV2Beta1 dialogflow;
@override
void initState() {
super.initState();
initPlugin();
}
Future<void> initPlugin()async{
final serviceAccount = ServiceAccount.fromString(
'${(await rootBundle.loadString('assets/credentials2.json'))}');
// Create a DialogflowGrpc Instance
dialogflow = DialogflowGrpcV2Beta1.viaServiceAccount(serviceAccount);
}
void handleSubmitted(text) async {
print(text);
_textController.clear();
ChatMessage message = ChatMessage(
text: text,
name: "You",
type: true,
);
setState(() {
_messages.insert(0, message);
});
DetectIntentResponse data = await dialogflow.detectIntent(text, 'en-US');
String fulfillmentText = data.queryResult.fulfillmentText;
if(fulfillmentText.isNotEmpty) {
ChatMessage botMessage = ChatMessage(
text: fulfillmentText,
name: "Bot",
type: false,
);
setState(() {
_messages.insert(0, botMessage);
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Chatbot Page'),
),
body: Column(children: <Widget>[
Flexible(
child: ListView.builder(
padding: EdgeInsets.all(8.0),
reverse: true,
itemBuilder: (_, int index) => _messages[index],
itemCount: _messages.length,
)),
Divider(height: 1.0),
Container(
decoration: BoxDecoration(color: Theme.of(context).cardColor),
child: IconTheme(
data: IconThemeData(color: Theme.of(context).accentColor),
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 8.0),
child: Row(
children: <Widget>[
Flexible(
child: TextField(
controller: _textController,
onSubmitted: handleSubmitted,
decoration: InputDecoration.collapsed(hintText: "Send a message to begin"),
),
),
Container(
margin: EdgeInsets.symmetric(horizontal: 4.0),
child: IconButton(
icon: Icon(Icons.send),
onPressed: () => handleSubmitted(_textController.text),
),
),
],
),
),
)
),
]),
);
}
}
class ChatMessage extends StatelessWidget {
ChatMessage({required this.text, required this.name, required this.type});
final String text;
final String name;
final bool type;
List<Widget> otherMessage(context) {
return <Widget>[
new Container(
margin: const EdgeInsets.only(right: 16.0),
child: CircleAvatar(child: new Text('B')),
),
new Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(this.name,
style: TextStyle(fontWeight: FontWeight.bold)),
Container(
margin: const EdgeInsets.only(top: 5.0),
child: Text(text),
),
],
),
),
];
}
List<Widget> myMessage(context) {
return <Widget>[
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Text(this.name, style: Theme.of(context).textTheme.subtitle1),
Container(
margin: const EdgeInsets.only(top: 5.0),
child: Text(text),
),
],
),
),
Container(
margin: const EdgeInsets.only(left: 16.0),
child: CircleAvatar(
child: Text(
this.name[0],
style: TextStyle(fontWeight: FontWeight.bold),
)),
),
];
}
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.symmetric(vertical: 10.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: this.type ? myMessage(context) : otherMessage(context),
),
);
}
}
CodePudding user response:
initPlugin
is a future method, It will take some frame to initialize the dialogflow
. You can make it nullable instead of using late,
DialogflowGrpcV2Beta1? dialogflow;
Now the place where you will use, you can do a null check.
Also a better way of doing this using FutureBuilder.
Future<DialogflowGrpcV2Beta?> initPlugin()async{
final serviceAccount = ServiceAccount.fromString(
'${(await rootBundle.loadString('assets/credentials2.json'))}');
// Create a DialogflowGrpc Instance
return DialogflowGrpcV2Beta1.viaServiceAccount(serviceAccount);
}
late final Future<DialogflowGrpcV2Beta> dialogflowFuture = initPlugin();
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future:dialogflowFuture,
builder: (context, snapshot) {
if(snapshot.hasError) return Text("Got Error");
if (snapshot.hasData){
final dialogflow = snapshot.data;
return Column(children: <Widget>[...
}
return CircularProgressIndicator(); //last
More about using FutureBuilder