The getter 'length' was called on null. fetch from api - flutter

I am trying to fetch data from api its splash screen of my app I want user wait 5 second when app is launched and then go to next screen but when I tried fetch data from api I received The getter 'length' was called on null. please help me here is my code I tried resolve it number of other resources but failed to find solution that's why I am posting my question is here please check and help
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_app/main.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
void main() {
runApp(new MaterialApp(
home: new SplashScreen(),
debugShowCheckedModeBanner: false,
routes: <String, WidgetBuilder>{
'/MyHomePage': (BuildContext context) => new MyHomePage()
},
));
}
class SplashScreen extends StatefulWidget {
#override
_SplashScreenState createState() => new _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
startTime() async {
var _duration = new Duration(seconds: 5);
return new Timer(_duration, navigationPage);
}
void navigationPage() {
Navigator.of(context).pushReplacementNamed('/MyHomePage');
}
bool _loading=true;
Map data;
List userData=null;
Future getData() async {
http.Response response = await http.get("https://livinghopemobile.com/public/api/fetch-site-settings?token=123ab_#_#AbCD");
data = json.decode(response.body);
debugPrint(response.body);
setState(() {
userData = data["data"];
_loading=false;
// print(userData[0]['title']);
});
}
#override
void initState() {
super.initState();
//startTime();
getData();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: ListView.builder(
itemCount:userData.length,
itemBuilder: (context, index) {
return Container(
child: Image.network(userData[index]['site_logo']),
);
}
)
);
}
}
Launching lib/ui/SplashScreen.dart on iPhone 11 Pro Max in debug mode...
Running Xcode build...
Xcode build done. 23.8s
Debug service listening on ws://127.0.0.1:60469/bL7bmRYyhoc=/ws
Syncing files to device iPhone 11 Pro Max...
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building SplashScreen(dirty, state: _SplashScreenState#5fa75):
The getter 'length' was called on null.
Receiver: null
Tried calling: length
The relevant error-causing widget was:
SplashScreen file:///Users/apple/livinghopev4/livinghope4ios/lib/ui/SplashScreen.dart:10:15
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
#1 _SplashScreenState.build (package:flutter_app/ui/SplashScreen.dart:61:30)
#2 StatefulElement.build (package:flutter/src/widgets/framework.dart:4612:27)
#3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4495:15)
#4 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4667:11)
...
════════════════════════════════════════════════════════════════════════════════════════════════════
flutter: {"status":200,"message":"Data fetched successfully","data":{"id":1,"site_logo":"https:\/\/livinghopemobile.com\/public\/storage\/site_logo\/270421_122025_image.png","site_name":"Living hope","created_at":null,"updated_at":"2021-04-27T07:20:26.000000Z"}}
[VERBOSE-2:ui_dart_state.cc(186)] Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'List<dynamic>'
#0 _SplashScreenState.getData.<anonymous closure> (package:flutter_app/ui/SplashScreen.dart:41:7)
#1 State.setState (package:flutter/src/widgets/framework.dart:1267:30)
#2 _SplashScreenState.getData (package:flutter_app/ui/SplashScreen.dart:40:5)
<asynchronous suspension>

This is because data is not type List, and userData is null hence there is no length to it when you are calling userData.length in ListView.builder.
Change null to [].
{"status":200,"message":"Data fetched successfully","data":{"id":1,"site_logo":"https:\/\/livinghopemobile.com\/public\/storage\/site_logo\/270421_122025_image.png","site_name":"Living hope","created_at":null,"updated_at":"2021-04-27T07:20:26.000000Z"}}
You could append the received data to userData, like: userData.add(data).

You try it:
itemCount:userData.length == null ? 0 : userData.length

Data is returning in Object and you are taking it as List. This is the reason you are getting the error.
Solution:
Don't use Listview.builder as api response is just an object(Map<String, dynamic>).
You can simply use
Image.network(userData['site_logo']),
and everthing will be fine.

Related

Unexpected "uncaught" exception passed to `onError` of `runZonedGuarded()` despite `try`/`catch`

Given the following complete minimal example run on Flutter 3.7.3 and Dart 2.19.2:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
WidgetsFlutterBinding.ensureInitialized();
runZonedGuarded(() {
runApp(const MyApp());
}, (error, stack) {
print('onError: $error\n$stack');
});
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override Widget build(BuildContext context) => const MaterialApp(home: MyHomePage());
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final http.Client _httpClient = http.Client();
#override
void initState() {
super.initState();
request().then((value) => print('then')).catchError((error) => print('catchError'));
}
Future<void> request() async {
try {
var request = http.Request('POST', Uri.parse('http://192.168.0.1'));
await _httpClient.send(request);
}
catch (error) {
print('catch: $error');
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: const Center(
child: Text('Push the button'),
),
floatingActionButton: FloatingActionButton(
onPressed: () => _httpClient.close(), // this leads to the exceptions
child: const Icon(Icons.add),
),
);
}
}
When the "+" button on the UI is pressed, a SocketException is both passed to the onError callback of the runZonedGuarded() and also the catch block of the HTTP request.
The console output is:
Restarted application in 720ms.
flutter: onError: SocketException: Connection attempt cancelled, host: 192.168.0.1, port: 80
#0 _NativeSocket.startConnect (dart:io-patch/socket_patch.dart:694:35)
#1 _RawSocket.startConnect (dart:io-patch/socket_patch.dart:1855:26)
#2 RawSocket.startConnect (dart:io-patch/socket_patch.dart:27:23)
#3 Socket._startConnect (dart:io-patch/socket_patch.dart:2078:22)
#4 Socket.startConnect (dart:io/socket.dart:763:21)
#5 _ConnectionTarget.connect (dart:_http/http_impl.dart:2466:20)
#6 _HttpClient._getConnection.connect (dart:_http/http_impl.dart:2906:12)
#7 _HttpClient._getConnection (dart:_http/http_impl.dart:2911:12)
#8 _HttpClient._openUrl (dart:_http/http_impl.dart:2766:12)
#9 _HttpClient.openUrl (dart:_http/http_impl.dart:2604:7)
#10 IOClient.send
#11 _MyHomePageState.request
#12 _MyHomePageState.initState
#13 StatefulElement._firstBuild
#14 ComponentElement.mount
--- 8< ---
#384 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3953:16)<…>
flutter: catch: Connection attempt cancelled, host: 192.168.0.1, port: 80
flutter: then
What I would like to know is...
Why are two apparently identical exceptions raised rather than one? (The two exception objects have different identity hash codes, but otherwise appear equivalent.)
Why, if the exception passed to onError is considered uncaught, does the stack trace for that very exception clearly show the try/catch block as an ancestor?
How can I catch the uncaught exception? So that it can be dealt with and not be uncaught?
Note: It's intentional for this demonstration that the HTTP request and subsequent client closure results in a SocketException. I'm not asking why this results in a SocketException. I'm asking why there are two exceptions, one of which is considered uncaught, despite the use of try/catch.
Note 2: Run on iOS device.

LateInitializationError: Field 'initialPosition' has not been initialized

I am trying to create map screen but I found the below error:
======== Exception caught by widgets library =======================================================
The following LateError was thrown building Consumer<MapViewModel>(dirty, dependencies: [_InheritedProviderScope<MapViewModel>]):
LateInitializationError: Field 'initialPosition' has not been initialized.
The relevant error-causing widget was:
Consumer<MapViewModel> file:///Users/mahmoudalharoon/Desktop/Air%20Forces/aireforces/lib/screens/BaseScreen.dart:44:14
When the exception was thrown, this was the stack:
#0 MapViewModel.initialPosition (package:airforces/screens/map/viewmodel/map_viewmodel.dart)
#1 MapScreen.build.<anonymous closure> (package:airforces/screens/map/view/map_screen.dart:19:27)
#2 Consumer.buildWithChild (package:provider/src/consumer.dart:180:19)
#3 SingleChildStatelessWidget.build (package:nested/nested.dart:259:41)
#4 StatelessElement.build (package:flutter/src/widgets/framework.dart:4648:28)
...
====================================================================================================
and this is the below ViewModel I have:
import 'package:airforces/enums/ScreenState.dart';
import 'package:airforces/screens/BaseViewModel.dart';
import 'package:geocoding/geocoding.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class MapViewModel extends BaseViewModel {
late LatLng? initialPosition;
late LatLng lastMapPosition = initialPosition!;
void getUserLocation() async {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high);
List<Placemark> placemarks = await placemarkFromCoordinates(
position.latitude, position.longitude);
initialPosition = LatLng(position.latitude, position.longitude);
print('${placemarks[0].name}');
setState(ViewState.Idle);
}
}
and this is the below map screen I have:
import 'package:airforces/screens/BaseScreen.dart';
import 'package:airforces/screens/map/viewmodel/map_viewmodel.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class MapScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return BaseScreen<MapViewModel>(
onFinish: (_) {
},
onModelReady: (mapViewModel) {
mapViewModel.getUserLocation();
},
builder: (context, mapViewModel, child){
return GoogleMap(
initialCameraPosition: CameraPosition(
target: mapViewModel.initialPosition!,
),
myLocationEnabled: true,
);
},
);
}
}
The issue is occurring because initialPosition is null until the late initialization occurs, but it is being converted to a non-nullable type before the late initialization occurs here: mapViewModel.initialPosition!.
You can resolve this one of two ways.
Return a default position if initialPosition is null when accessing it.
target: mapViewModel.initialPosition ?? [defaultPosition];
Display a loading widget until initialPosition is initialized, then display GoogleMap.
Both of these solutions will require a minor state management solution in order to update the widget when initialPosition is finally initialized.

StreamBuilder<FileSystemEntity>(dirty, state: _StreamBuilderBaseState<FileSystemEntity, AsyncSnapshot<FileSystemEntity>>#25d1b)

I have got an error while working with Stream builders.
In my code, I used if(snapshot.data != null) { list.add(snapshot.data); } but I m getting a msg that add was called on null. I even added print('') statement to check if snapshot.data is null, but it is working fine with print() too. So I m not at all understanding how to solve this error. Someone please respond. Thanks in advance.
Here is my code
class Wrapper extends StatefulWidget {
#override
_WrapperState createState() => _WrapperState();
}
class _WrapperState extends State<Wrapper> {
Stream<FileSystemEntity> mystream;
var _directory;
void getfilesdata() async
{
_directory = await getApplicationDocumentsDirectory();
await Directory('${_directory.path}/data').create(recursive: true);
mystream = Directory('${_directory.path}/data').list().map((data) => data);
await Directory('${_directory.path}/documents').create(recursive: true);
}
#override
void initState() {
super.initState();
getfilesdata();
}
#override
Widget build(BuildContext context) {
List<FileSystemEntity> alldata;
return StreamBuilder<FileSystemEntity>(
stream: mystream,
builder: (context, snapshot) {
if(!snapshot.hasData)
{
print('No data yet');
return Loading();
}
else
{
if(snapshot.data != null && !snapshot.hasError)
{
print(snapshot.data);
alldata.add(snapshot.data);
}
if(snapshot.connectionState==ConnectionState.done)
{
return HomeScreen(alldata: alldata);
}
else return Loading();
}
}
);
}
}
And this is the result:
Performing hot restart...
Syncing files to device ZUK Z2132...
Restarted application in 1,734ms.
I/flutter (11840): No data yet
I/flutter (11840): No data yet
I/flutter (11840): File: '/data/user/0/com.example.easyscan/app_flutter/data/data[0]'
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building StreamBuilder<FileSystemEntity>(dirty, state: _StreamBuilderBaseState<FileSystemEntity, AsyncSnapshot<FileSystemEntity>>#25d1b):
The method 'add' was called on null.
Receiver: null
Tried calling: add(Instance of '_File')
The relevant error-causing widget was:
StreamBuilder<FileSystemEntity> file:///home/praneeth/AndroidStudioProjects/easyscan/lib/wrapper.dart:40:12
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 _WrapperState.build.<anonymous closure> (package:easyscan/wrapper.dart:53:25)
#2 StreamBuilder.build (package:flutter/src/widgets/async.dart:509:81)
#3 _StreamBuilderBaseState.build (package:flutter/src/widgets/async.dart:127:48)
#4 StatefulElement.build (package:flutter/src/widgets/framework.dart:4619:28)
...
════════════════════════════════════════════════════════════════════════════════════════════════════
Your error is because allData is null so you cannot call the add() method.
You can declare your variable as follow:
List<FileSystemEntity> alldata = [];
By doing this allData will be initialized as an empty list and you will be able to call its methods.

Unimplemented handling of missing static target, Flutter

I'm writing my Flutter code but I keep getting the error of Unimplemented handling of missing the static target. there is no other error give so I don't know why I'm getting this and there is no way for me to debug it.
The error I'm getting is:
══════ Exception caught by widgets library ═══════════════════════════════════
The following _CompileTimeError was thrown building Wrapper(dirty, dependencies: [InheritedProvider<User>], state: _Wrapper#576d6):
Unimplemented handling of missing static target
The relevant error-causing widget was
Wrapper
lib\main.dart:28
When the exception was thrown, this was the stack
#0 StatefulElement.build
package:flutter/…/widgets/framework.dart:4334
#1 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4223
#2 Element.rebuild
package:flutter/…/widgets/framework.dart:3947
#3 StatefulElement.update
package:flutter/…/widgets/framework.dart:4413
#4 Element.updateChild
package:flutter/…/widgets/framework.dart:2977
...
════════════════════════════════════════════════════════════════════════════════
Reloaded 5 of 544 libraries in 350ms.
════════ Exception caught by widgets library ═══════════════════════════════════
Unimplemented handling of missing static target
The relevant error-causing widget was
Wrapper
My code is :
import 'package:sociagrowapp/models/user.dart';
import 'package:sociagrowapp/HomePages/Home.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:sociagrowapp/Authenticate/authenticate.dart';
//import 'package:package_info/package_info.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:sociagrowapp/services/firestore.dart';
import 'package:http/http.dart' as http;
class Wrapper extends StatefulWidget {
#override
createState() => _Wrapper();
}
class _Wrapper extends State<Wrapper> {
#override
Widget build(BuildContext context) {
Future getversionnumber() async {
var data = http.get('https://sociagrow.com/version.html');
print(data);
return data;
}
return FutureBuilder(
future: getversionnumber(),
builder: (BuildContext context, snapshot) {
if (snapshot.hasData) {
final user = Provider.of<User>(context);
print(user);
var version = snapshot.data;
// return either the Home or Authenticate widget
if (version == false) {
return Text('Oh no You need to update');
} else {
if (user == null) {
print('Should Changed 3');
return Scaffold(body: Authenticate());
} else {
return PageData();
}
}
} else {
return SpinKitThreeBounce(
color: Colors.blue,
);
}
});
}
}
The strange part is that when I debug it in visual studio code it runs but when I resave and hot reload it I get this error. The problem is not in the http.get() because I got the error with other future functions and firestore as well. really strange though I haven't encountered this type of error and I can't find anything about this error in the internet that could be helpful.
May be hot-reload cache lead to this problem, I just encounter the same problem and I fixed it by stop project then restart it.
You can solve this problem by stopping the debugging or terminate the app.
Then, try to restart or debug the app.

Race condition in Stateful widget with parameter

I'm having a race condition of data from a BehaviorSubject's stream not populating/updating the state before the build function returns.
content-detail.dart
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:domain_flutter/application-bloc.dart';
import 'package:domain_flutter/content.dart';
import 'package:domain_flutter/tag_chips.dart';
import 'package:cached_network_image/cached_network_image.dart';
class ContentDetail extends StatefulWidget {
final String slug;
ContentDetail({Key key, this.slug}) : super(key: key);
#override
State<StatefulWidget> createState() => _ContentDetailState();
}
class _ContentDetailState extends State<ContentDetail> {
Content _content = Content();
_getContent() {
print(widget.slug);
applicationBloc.contentOutput.map( (contents) =>
contents.where((item) => item.slug == widget.slug).toList())
.listen((data) => {
if (this.mounted) {
setState(() => _content = data.first)
}
});
}
#override
void initState() {
super.initState();
_getContent();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: _content != null ? Text(_content.title) : Text(''),
),
body:
SafeArea(
child: Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
child: ListTile(
contentPadding: EdgeInsets.all(0),
title: Text(_content.title,style: TextStyle(fontWeight: FontWeight.bold)),
subtitle: Text(
DateFormat('dd.MM.yyyy').format(_content.changed),
style: TextStyle(fontSize: 12),
),
)),
TagChips(_content.tags),
CachedNetworkImage(
placeholder: (context, url) => CircularProgressIndicator(),
imageUrl: 'https://domain.tld/files/${_content.image}'),
],
),
),
),
);
}
}
The widget renders, but before it's rendered I receive an error.
If content isn't initialized I receive a different error.
What I mean by content initialized is
Content _content = Content();
content initialized:
The following assertion was thrown building ContentDetail(dirty, state: _ContentDetailState#15727):
A non-null String must be provided to a Text widget.
'package:flutter/src/widgets/text.dart':
Failed assertion: line 269 pos 10: 'data != null'
Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
https://github.com/flutter/flutter/issues/new?template=BUG.md
User-created ancestor of the error-causing widget was:
MaterialApp file:///home/darko/AndroidStudioProjects/domain_flutter/lib/main.dart:24:12
When the exception was thrown, this was the stack:
#2 new Text (package:flutter/src/widgets/text.dart:269:10)
#3 _ContentDetailState.build (package:domain_flutter/content_detail.dart:41:35)
#4 StatefulElement.build (package:flutter/src/widgets/framework.dart:4047:27)
#5 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3941:15)
#6 Element.rebuild (package:flutter/src/widgets/framework.dart:3738:5)
...
content uninitialized:
The following NoSuchMethodError was thrown building ContentDetail(dirty, state: _ContentDetailState#2be0b):
The getter 'title' was called on null.
Receiver: null
Tried calling: title
User-created ancestor of the error-causing widget was:
MaterialApp file:///home/darko/AndroidStudioProjects/domain_flutter/lib/main.dart:24:12
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1 _ContentDetailState.build (package:domain_flutter/content_detail.dart:53:38)
#2 StatefulElement.build (package:flutter/src/widgets/framework.dart:4047:27)
#3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3941:15)
#4 Element.rebuild (package:flutter/src/widgets/framework.dart:3738:5)
...
So yeah, there is no data when it's trying to render the component... or Widget/s rather.
I should probably show my applicationBloc
import 'dart:async';
import 'package:domain_flutter/application-entities.dart';
import 'package:domain_flutter/content.dart';
import 'package:domain_flutter/tag.dart';
import 'package:rxdart/rxdart.dart';
class ApplicationBloc {
final _applicationEntities = ApplicationEntities();
Sink<List<Content>> get contentInput => _contentInputController.sink;
Sink<List<Tag>> get tagInput => _tagInputController.sink;
Stream<List<Content>> get contentOutput => _contentOutputSubject.stream;
Stream<List<Tag>> get tagOutput => _tagOutputSubject.stream;
final _contentInputController = StreamController<List<Content>>();
final _tagInputController = StreamController<List<Tag>>();
final _contentOutputSubject = BehaviorSubject<List<Content>>();
final _tagOutputSubject = BehaviorSubject<List<Tag>>();
ApplicationBloc() {
_contentInputController.stream.listen(_handleContentInput);
_tagInputController.stream.listen(_handleTagInput);
}
void dispose() {
_contentInputController.close();
_contentOutputSubject.close();
_tagInputController.close();
_tagOutputSubject.close();
}
void _handleContentInput(List<Content> contentList) {
_applicationEntities.updateContent(contentList);
_contentOutputSubject.add(contentList);
}
void _handleTagInput(List<Tag> tagList) {
_applicationEntities.updateTags(tagList);
_tagOutputSubject.add(tagList);
}
}
final applicationBloc = ApplicationBloc();
You probably guessed, the idea is to load the JSON from a web service then provide it application wide via global variable.
That works without errors for everything but the ContentDetail class.
This ContentDetail class is almost a copy of another component that does almost the same, it filters by a tag slug and renders a list of Content.
This here only wants 1 item from the stream, Content with a specific slug property.
class Content {
// ...
final String slug;
}
As you can see I'm passing the slug in the ContentDetail constructor and my _ContentDetailState is accessing its property via widget.slug.
The _getContent() function of the ContentListByTagSlug class in comparison:
void _getContent() {
applicationBloc.contentOutput.map(
(contents) => contents.where(
(item) => item.tags.any((tag) => tag.slug == widget.tag.slug)
).toList()
)
.listen((data) => {
if (this.mounted) {
setState(() => {content = data})
}
});
}
This works, while only getting 1 item from it doesn't (see 1st code snippet).
This is how I define the FlatButton to open the ContentDetail page:
FlatButton(
child: Text('Read more'),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
ContentDetail(slug: content[index].slug))),
),
It's valid, the slug is passed as the result of the print function indicates.
I'm not sure what to do to ascertain that the _content variable is populated before the build function is executed.
In Angular one creates a resolver, which then populates data before the component is created/initialized.
In Flutter?
Note I'm not using the bloc package, but put the streams in a dedicated class, then use setState to update the state in the listening classes, as the bloc package seems overkill for this scenario.
3 widgets (4 if you count the drawer)
1 displaying an unfiltered list
2 displaying a list filtered by tag slug
3 displaying one item filtered by tag slug
only the latter has errors.
update1: I even removed the if (this.mounted) check in _getContent() and I'm calling _getContent() again in the builder if _content is null.
Then I have changed _content to be a List and am getting _content.first.title which results in
Bad state: No element
But the widget is still rendered correctly.
So it seems that there are 2 invocations of the widget. One that throws errors, which is discarded and one that doesn't which is kept. I'm not familiar with the internals so that's my best guess.
This is answered in this answer.
What I'm taking away from it is
don't initialize variables that are meant to be filled by a stream
provide a check in the builder whether the value to be filled in null
if null render a loading screen else render the desired widget with populated state