How to show custom warning when FutureBuilder snapshot data equals to 0 (zero)? - warnings

In my Flutter app body section I use FutureBuilder. If snapshot.hasData then I show the Data in body. My problem is that sometimes the snapshot data is 0 (zero). I need to use stack or similar to show user a warning with stating that “currently data is not available”. How do I do that?
body: new Center(
child: new FutureBuilder(
future: getCurrencyJsonData(),
builder: (context, snaphot) {
if (snaphot.hasData) {
return new ListView(

Just add a if into your builder..
if (snaphot.data.length == 0) {
return new Stack(...);
}

Related

how to show the dialog box when session expired or getting response 401 in flutter

My application has a user token and it expires after some time the user login. I got response code 401 and want to navigate to the login page, I am using dio and flutter_secure_storage to save tokens.
else if (e.response?.statusCode == 401) {
//here I want to show the dialog box or navigate to the login page
}
print(getDioException(e));
throw Exception(getDioException(e));
}
If you want to show popup please do like below.
else if (e.response?.statusCode == 401) {
showPopUpAlert();//here you have to call your popup function
}
print(getDioException(e));
throw Exception(getDioException(e));
}
//popup UI implementation
showPopUpAlert() {
showDialog(
context: context,
builder: (_) => AlertDialog(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0))),
content: Builder(builder: (context) {
return StatefulBuilder(builder: (context, stateMaintain) {
return SizedBox(
width: Responsive.isMobile(context)
? Responsive.screenWidth(context) / 1.1
: Responsive.screenWidth(context) / 2,
height: 350,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
AutoSizeText('Popup text',
style:
Theme.of(context).textTheme.headline1),
],
),
);
});
}),
));
}
After some time of research, I found the answer.
we need to create a global key for navigating and after we got the 401 we need to navigate the login page.
define global key final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
pass the value in MaterialApp
navigatorKey: navigatorKey,
and use into your class
navigatorKey.currentState?.pushNamed('/LoginScreen');

FutureBuilder displays that data is null even tho it has value and still proceeds as normal [Flutter]

Hi currently Im working with local json file where I want to use some data from it. I have modeled it accordingly to that json file and when I print it out it works as normal. But when I run it in debug mode it stops at this points saying this :_CastError (type 'Null' is not a subtype of type 'List<UrlCheckModel>' in type cast)
This is my code:
FutureBuilder(
future: readJsonData(),
builder: (context, data) {
if (data.hasError) {
//in case if error found
return Center(child: Text("${data.error}"));
}
List<UrlCheckModel> items = data.data as List<UrlCheckModel>;
Where readJsonData is:
Future<List<UrlCheckModel>> readJsonData() async {
//read json file
final jsondata =
await rootBundle.rootBundle.loadString('jsonfile/malicious.json');
//decode json data as list
final list = json.decode(jsondata) as List<dynamic>;
//map json and initialize using DataModel
return list.map((e) => UrlCheckModel.fromJson(e)).toList();
}
My question is why is this error happening even tho when I run the app it works fine (at brief 1 second time period the error appears) and how can I resolve this. Looking forward to your replies. (If needed I can post the whole code for this page).
Ok so it seams even tho the json file is stored localy and Im not fetching it via API calls it needs to be initialized, so with help of #temp_ one viable solution is like this:
if (data.data == null || data.hasError) {
//in case if error found
return const Center(
child: Text(
'Please wait',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 26,
color: Color.fromRGBO(255, 125, 84, 1),
fontWeight: FontWeight.bold,
),
),
);
}
First off
Before all, you have a error in your widget configuration:
FutureBuilder(
// Do not call the async function directly
future: readJsonData(),
// ...
)
This will result on new Future being instantiated every rebuild, which kills device memory and your app will eventually be killed by the OS.
By the docs:
The future must have been obtained earlier, e.g. during State.initState, State.didUpdateWidget, or State.didChangeDependencies. It must not be created during the State.build or StatelessWidget.build method call when constructing the FutureBuilder. If the future is created at the same time as the FutureBuilder, then every time the FutureBuilder's parent is rebuilt, the asynchronous task will be restarted.
Then you should do something like this:
Future<List<UrlCheckModel>> _future;
void initState() {
super.initState();
_future = readJsonData();
}
Widget build(BuildContext context) {
return FutureBuilder<List<UrlCheckModel>>(
future: _future,
// ..
);
}
Now fixing the actual error
Since the rendering process is sync, which means Flutter can't wait your async process finish to render the first frame of your widget, you should be aware the data will be null in the first snapshot (AsyncSnapshot<T>.nothing()), in the docs:
For a future that completes successfully with data, assuming initialData is null, the builder will be called with either both or only the latter of the following snapshots:
AsyncSnapshot<String>.withData(ConnectionState.waiting, null)
AsyncSnapshot<String>.withData(ConnectionState.done, 'some data')
As you see, your 'data' is actually of type AsyncSnapshot<T>, then:
FutureBuilder<List<UrlCheckModel>>(
future: _future,
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return Loading();
}
if (snapshot.hasError) {
return HandleYourError();
}
List<UrlCheckModel> items = snapshot.data as List<UrlCheckModel>;
return HappyEnd(items: items);
}
);
See FutureBuilder<T> class reference for details

Flutter getx json

First of all, I apologize to everyone for my low level of English. I want to make an application for a live broadcasting radio station. json link of radio site "http://radyo.comu.edu.tr/json/". This link is refreshed every 5 seconds. and json data is also changing. How can I follow a path from the application?
You can cache the response by using flutter cache manager Flutter Cache Manager, store it somewhere and use it. For storage you can use shared preferences,sqlite, hive etc there are a lot of options afterwards
you can use stream builder where data is continually updating
https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html
StreamBuilder<int>(
stream: generateNumbers,
builder: (
BuildContext context,
AsyncSnapshot<int> snapshot,
) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
} else if (snapshot.connectionState == ConnectionState.active
|| snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return const Text('Error');
} else if (snapshot.hasData) {
return Text(
snapshot.data.toString(),
style: const TextStyle(color: Colors.red, fontSize: 40)
);
} else {
return const Text('Empty data');
}
} else {
return Text('State: ${snapshot.connectionState}');
}
},
),

error: Undefined name 'widget' in Dart when trying to build navigation

Can someone help me? Newbie with Flutter here.
I have this:
class SecondRoute extends StatelessWidget {
final Place? place;
const SecondRoute({Key? key, this.place}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text(widget.place!.text!),
),
),
);
}
And:
class PlaceDetail extends StatefulWidget {
final Place? place;
PlaceDetail({Key? key, this.place}) : super(key: key);
#override
_PlaceDetailState createState() {
return _PlaceDetailState();
}
}
I successfully can navigate to the next page, but the problem is with this part:
child: Text(widget.place!.text!)
I am trying to show some content that I fetch with JSON. In a different widget, that specific widget.place!.text! works like a charm, but in this class and widget, I can't get it to work and t thus I get the error:
error: Undefined name 'widget'
If I extend it to State , I get the error:
error: The return type 'SecondRoute' isn't a 'Widget'
I tried to follow the documentation here:
https://flutter.dev/docs/cookbook/navigation/navigation-basics
As I mentioned, the navigation itself works, but trying to fetch data from JSON that I had in a widget gives me the error.
Edit:
Text(${place?.text!}")
The above gives me NULL. Any chance I can get this variable sent to the new page/screen without giving me NULL value?
child: Text(widget.place!.text!)
should be
child: Text(this.place!.text!)
or simply
child: Text(place!.text!)
Although you should think about your usage of !. It should not be neccessary here.

Flutter map_view use map_view as widget

I would like to ask on how to show the map fullscreen using the function MapView.Show function on map_view dart framework which I couldn't implement as a widget in flutter. see my code below:
MapView showMap() {
return _mapView.show(new MapOptions(
mapViewType: MapViewType.normal,
initialCameraPosition:
new CameraPosition(new Location(10.31264, 123.91139), 12.0),
showUserLocation: true,
));
}
should be put inside the child in widget.
#override
Widget build(BuildContext context) {
return new Container(
color: Colors.red,
height: double.infinity,
width: double.infinity,
child: showMap(), // surprisingly not working
);
}
I looked into tutorials on this implementation but it seems I haven't seen any liable sources on this implementation. Does anyone knew how to implement this one? Thanks!
Note: I want to implement as a fullscreen widget.
As far as I know, you have to show the Map_View calling a function when an event happens (like when a button is pressed). It's not a Widget like a Text or a Padding.
If you want to open a fullscreen Map I'd suggest you to try, for example, this.
#override
Widget build(BuildContext context) {
return new Container(
color: Colors.red,
height: double.infinity,
width: double.infinity,
child: Center(
child: RaisedButton(
onPressed: () => showMap(),
child: Text("Click me!"),
),
),
);
}