I am building a Dictionary app using using api owlbot. My code Run fines shows no error. But after the run time i am getting error ════════ Exception caught by widgets ═══════════════════════════════════════════ Null check operator used on a null value ════════════════════════════════════════════════════════════════════
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: DictionaryPage(),
);
}
}
My Dictionary Page Code:
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart';
import 'package:flutter/material.dart';
class DictionaryPage extends StatefulWidget {
@override
_DictionaryPageState createState() => _DictionaryPageState();
}
class _DictionaryPageState extends State<DictionaryPage> {
String url = "https://owlbot.info/api/v4/dictionary/";
String token = "Your Key";
TextEditingController textEditingController = TextEditingController();
// Stream for loading the text as soon as it is typed
late StreamController streamController;
Stream? _stream;
Timer? _debounce;
// search function
searchText() async {
if (textEditingController.text.length == 0) {
streamController.add(null);
return;
}
streamController.add("waiting");
Response response =
await get(url + textEditingController.text.trim() as Uri,
// do provide spacing after Token
headers: {"Authorization": "Token " + token});
streamController.add(json.decode(response.body));
}
@override
void initState() {
super.initState();
streamController = StreamController();
_stream = streamController.stream;
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
title: Text(
"Dictionary nw",
style: TextStyle(color: Colors.white),
),
centerTitle: true,
bottom: PreferredSize(
preferredSize: Size.fromHeight(45),
child: Row(
children: [
Expanded(
child: Container(
margin: const EdgeInsets.only(left: 12, bottom: 11.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24.0),
color: Colors.white),
child: TextFormField(
onChanged: (String? text) {
if (_debounce!.isActive) _debounce?.cancel();
_debounce =
Timer(const Duration(milliseconds: 1000), () {
searchText();
});
},
controller: textEditingController,
decoration: InputDecoration(
hintText: "Search for a word",
contentPadding: const EdgeInsets.only(left: 24.0),
// removing the input border
border: InputBorder.none,
),
),
),
),
IconButton(
icon: Icon(
Icons.search,
color: Colors.white,
),
onPressed: () {
searchText();
},
)
],
),
),
),
body: Container(
margin: EdgeInsets.all(8),
child: StreamBuilder(
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Center(
child: Text("Enter a search word"),
);
}
if (snapshot.data == "waiting") {
return Center(
child: CircularProgressIndicator(),
);
}
// output
return ListView.builder(
itemCount: snapshot.data["definitions"].length,
itemBuilder: (BuildContext context, int index) {
return ListBody(
children: [
Container(
color: Colors.grey[300],
child: ListTile(
leading: snapshot.data["definitions"][index]
["image_url"] ==
null
? null
: CircleAvatar(
backgroundImage: NetworkImage(snapshot
.data["definitions"][index]["image_url"]),
),
title: Text(textEditingController.text.trim() +
"(" +
snapshot.data["definitions"][index]["type"] +
")"),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
snapshot.data["definitions"][index]["definition"]),
)
],
);
},
);
},
stream: _stream,
),
),
),
);
}
}
From my study I think this error occurred from ,
if (_debounce!.isActive) _debounce?.cancel();
_debounce =
Timer(const Duration(milliseconds: 1000), () {
searchText();
});
},
this, which i need to change according to this ,
Use a local variable
var f = foo;
if (f != null) {
var len = f.length; // Safe
}
Use ?. and ??
var len = foo?.length ?? 0;