Why this shake functionality not working in flutter? - flutter

This ShakePlugin is not working with this piece of code,when im just using this code without these api calls and all its working fine.
class MyAppState extends State<MyApp> {
List data;
String _search = 'nature';
int index = 0;
File imageFile;
String imageData;
bool dataLoaded;
var path;
int count = 10;
FlutterShakePlugin _shakePlugin;
void initState() {
super.initState();
_shakePlugin = FlutterShakePlugin(
onPhoneShaken: () {
setState(() {
count=count+10;
});
},
},
)..startListening();
}
void dispose() {
super.dispose();
_shakePlugin.stopListening();
}
Future<String> getjsondata() async {
try {
var response = await http.get(
'https://api.unsplash.com/search/photos?per_page=${count}&client_id=TcAQEO3JoMG90U7Rl-YUiDo1x9XbZukzMOMQhxUVCV4&query=${_search}');
setState(() {
var converted = json.decode(response.body);
data = converted['results'];
});
} catch (e) {}
return 'success';
}
void saveImage(int i) async {
var url = data[i]['urls']['small'].toString();
var imageId = await ImageDownloader.downloadImage(url);
path = await ImageDownloader.findPath(imageId);
}
#override
Widget build(BuildContext context) {
getjsondata();
return GestureDetector(
child: SwipeDetector(
child: Container(
child: Image.network(
data[index]['urls']['small'],
I want to increase the count of images i recieve from api on shake of screen but this is not working even if i have installed all the libraries and all.

Calling your getjsondata method in the build method will cause the ui to render infinitely because you're calling setState in getjsondata. I think the shake plugin is working fine but its result is void because the screen is in an infinite render state.
If you move getjsondata to a FutureBuilder, remove the setState call from inside the getjsondata method and render your ui on the result of the Future your code should work.

Related

Data only fetchs when hot reload flutter

I know this has been asked previously, but I canĀ“t get it by my own.
I have a fetching method:
dynamic getResponse() async {
response = await api.getGlobalResponse();
resp = GlobalResponse.fromJson(jsonDecode(response));
if (resp != null) {
if (resp!.almacenes != null) {
for (Almacen alm in resp!.almacenes!) {
int count = 0;
for (var opt in options) {
if (opt != alm.name) {
continue;
} else {
count += 1;
break;
}
}
if (count <= 0) options.add(alm.name.toString());
}
}
}
return response;
}
which resolves OK after hot reloading.
I call it on the initState() in my first screen after login, like this:
class _LoggedInState extends State<LoggedIn> {
final _scaffoldKey = GlobalKey<ScaffoldState>();
#override
void initState() {
super.initState();
getResponse();
setState(() {
resp = resp;
});
page = getPage();
}
#override
didChangeDependencies() {
getResponse();
setState(() {
resp = resp;
});
super.didChangeDependencies();
}
#override
Widget build(BuildContext context) {
if (getToken()) {
return SafeArea(
child: Scaffold(
body: page,
),
);
} else {
return getLoginScreen();
}
}
}
The getPage() returns correctly loaded from fetch after hot reload, but I cant figure out how to auto load from the very first time.
I have already tryed ValueNotifiers and ValueListenables, without luck.
willyou please help this fool?
It is generally recommended to avoid using the dynamic type in Dart, as it can lead to potential runtime errors if the wrong type of data is returned or passed in. Instead, it is better to specify the specific type that you are expecting.
If you are sure that you have to use dynamic here, then change return type of getResponse to Future<dynamic> because the function is asynchronous.
In the widget, in initState and didChangeDependencies methods after calling getResponse wait for its response then call setState.
getResponse().then((resp) =>
setState(() {
resp = resp;
}));
This code calls the getResponse method and waits for the response to be returned. Once it is received, it calls the setState method and updates the state of the widget with the returned data.

Flutter widget unmounting without dispose

So a piece of code I wrote needs to run on both web and mobile. And since some libraries like dart: io on the web and can't use dart:html on mobile. So in order to pick images on the web, I tried to use ImagePicker which returns an X-File, turns the X-File to bytes, and uses Image. memory().
This is the piece of code that I've been trying:
class _CanvasImageItemState extends State<CanvasImageItem> {
Uint8List? imageBytes;
XFile? file;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
// widgets
}
Widget buildPicker(BuildContext context) {
if (kDebugMode) {
print("picker loaded");
}
return InkWell(
onTap: () async {
FocusedItemModel.of(context).focus(widget.item as LocalImageItem);
if (!kIsWeb) {
// Some piece of code for mobile
} else {
await _pickImage();
}
},
child: ..some other widgets
);
}
}
_pickImage() async {
final ImagePicker _picker = ImagePicker();
file = await _picker.pickImage(source: ImageSource.gallery);
Uint8List? bytes = await file!.readAsBytes();
if (mounted) {
setState(() {});
imageBytes = bytes;
} else {
imageBytes = bytes;
}
if (kDebugMode) {
print("Checking File: ${file!.path}");
print("Checking imageBytes: ${imageBytes!.length}");
}
}
The problem is although I did not dispose() the widget or used dispose() anywhere in the project itself but I am getting
setState() called after dispose() error. So I tried checking if(mounted) before trying to update the value of imageBytes but in that case, it's taking two tries to pick the image.
As you can see I even tried to print the path of xFile and imageBytes which is getting printed properly. But I cannot set the state.
N.B: The CanvasImageItem is child of another widget called CanvasMovableItem. Any suggestion where the problem is occurring from? I've checked all possible codes that might unmount or dispose of the widget.
Am I missing something very simple?

flutter - FutureBuilder auto rebuild each time press a button in the screen

I try to use FutureBuilder in Flutter to wait ulti my initState is finished then buil the UI for the app.
But when the app is running, the screen keep rebuilding each time I press another button (the button does totally different thing).
Future loadUser() async {
String jsonString = await storage.read(key: "jwt");
final jsonResponse = json.decode(jsonString);
loggedUser = new LoggedUser.fromJson(jsonResponse);
print(loggedUser.token);
getProfile();
getJourneyByUserId()
.then((receivedList){
addRanges(receivedList);});
}
Future<List<Journey>>getJourneyByUserId() async {
var res = await http.get(
Uri.parse("$baseUrl/journeys/userid=${loggedUser.user.userId}"),
headers: {
'Content_Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer ${loggedUser.token}',
},
);
if (res.statusCode == 200) {
print("Get journeys successfully");
}
var data = jsonDecode(res.body);
List idList = [];
for (var i in data) {
idList.add(i["journeyId"]);
}
for (var i in idList) {
var res = await http.get(
Uri.parse("$baseUrl/journeys/$i"),
);
var data = jsonDecode(res.body);
Journey userJourney = new Journey.fromJson(data);
setState(() {
journeyList.add(userJourney);
});
}
print("Journey ${journeyList.length}");
return journeyList;
}
addRanges(journeyList){
setState(() {
rangeList=[];
});
if (journeyList.isNotEmpty) {
for (var i in journeyList) {
DateTime startDate =
DateTime(i.startDate.year, i.startDate.month, i.startDate.day);
DateTime endDate =
DateTime(i.endDate.year, i.endDate.month, i.endDate.day);
setState(() {
rangeList.add(PickerDateRange(startDate, endDate));
});
}
}
print("Range ${rangeList.length}");
return rangeList;
}
returnRange() {
List<PickerDateRange> list = [];
for(int i =0; i<rangeList.length;i++){
list.add(rangeList[i]);
}
return list;
}
Future functionForBuilder() async {
return await returnRange();
}
//initState function
#override
void initState() {
super.initState();
loadUser();
functionForBuilder();
}
//build the UI
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("$_name's Profile",style: TextStyle(color: kColorPalette4),),
centerTitle: true,
),
body: Container(
child: FutureBuilder(
future: functionForBuilder(),
builder: (BuildContext context,AsyncSnapshot snapshot){
//here I set the condition for each case of snapshot
}
I have read some documents say that I should assign the functionForBuilder() to a Future variable when initState then use it in the future child of FutureBuilder. Example:
Future _future;
//initState function
#override
void initState() {
super.initState();
loadUser();
_future=functionForBuilder();
}
// then with the FutureBuilder
future: _future
With this way the screen is not rebuild anymore but my function returnRange() seems like not running as my expextation (I called the returnRange() once in the build() function).
Thanks in advance for your answer!
Whenever you assign to the _future variable again, you must do that inside a setState block, otherwise the widget will not rebuild with the new future.
For example:
void updateData() {
setState(() {
_future = functionForBuilder();
});
}
If you use FutureBuilder, it rebuild items again and again.
Try two ways:
Don't use `future: functionForBuilder(), comment it.
Remove FutureBuilder(), simply use Container().
And let me know any issue?
Code:
call your future in the initstate method not in the build as shown in the example.
class MyPage extends StatefulWidget { #override State<MyPage> createState() => _MyPageState(); } class _MyPageState extends State<MyPage> { // Declare a variable. late final Future<int> _future; #override void initState() { super.initState(); _future = _calculate(); // Assign your Future to it. } // This is your actual Future. Future<int> _calculate() => Future.delayed(Duration(seconds: 3), () => 42); #override Widget build(BuildContext context) { return Scaffold( body: FutureBuilder<int>( future: _future, // Use your variable here (not the actual Future) builder: (_, snapshot) { if (snapshot.hasData) return Text('Value = ${snapshot.data!}'); return Text('Loading...'); }, ), ); } }

Unknown LateInitializationError in Flutter

I have a flutter widget which retrieves Json information from an API and displays a widget of that information. My initState is as follows:
class _BuildCardsWidgetState extends State<BuildCardsWidget> {
bool display = false;
late Resource _resource;
Future<Resource> fetchResource(Build build) async {
var url = Uri.parse(APIURL); <-actual url link hidden
final response = await http.get(url);
var resourceReturn = json.decode(response.body);
var resourceJson = resourceReturn[0]['resource'];
return Resource.fromJson(resourceJson, build);
}
#override
void initState() {
fetchResource(widget.build).then((value) =>
this.setState(() {
_resource = value;
display = true;
}));
super.initState();
}
#override
Widget build(BuildContext context) {
return ... <- _resource is used within build
However, whenever the program gets to the line
final response = await http.get(url);
This error is thrown:
The following LateError was thrown building BuildCardsWidget(dirty, state: _BuildCardsWidgetState#b3c7a):
LateInitializationError: Field '_resource' has not been initialized.
The thing that confuses me is this error flashes, but then right after the widget is correctly built and it runs smoothly. Any suggestions on how to fix this or on how to ignore this error since it does appear to work after the initial error?
Try to avoid using asynchronous functions inside initState, if it's not properly handled with await in a separate function, the widget won't load your data before build your widgets. A quick and simple way to solve this is to use a FutureBuilder().
class _BuildCardsWidgetState extends State<BuildCardsWidget> {
Future<Resource> fetchResource(Build build) async {
var url = Uri.parse(APIURL); <-actual url link hidden
var resourceReturn = json.decode(response.body);
var resourceJson = resourceReturn[0]['resource'];
return Resource.fromJson(resourceJson, build);
}
#override
Widget build(BuildContext context) {
return FutureBuilder<Resource>(
future: fetchResource(build),
builder: (context, snapshot) {
return SizedBox();
}
if(snapshot.hasError) {
/// Handle error
}
}
);
}
}

getting code to run upon widget creation flutter

I have a flutter camera app and am able to get a recorded video to play. The problem is, I am only able to get it to play when a button is pressed. How do I get the code to run when the widget(screen) is created instead of when the button is pressed so I don't have to press a button to get it to play? Here is my code:
Here is the code for when the button is pressed:
//raised button
RaisedButton(
onPressed: () {stopButtonPressed();},
//stopButtonPressed
void stopButtonPressed() {
print('stopButtonPressed hit');
stopVideoRecording().then((_) {
print('StopVideoRecording complete');
});
}
//stopVideoRecording
Future<void> stopVideoRecording() async {
print('stopVideoRecording hit');
await _startVideoPlayer();
}
//_startVideoPlayer
Future<void> _startVideoPlayer() async {
print('_startVideoPlayer hit');
print(Provider.of<SendDataModel>(context, listen: false).displayImageVideo());
final VideoPlayerController vcontroller =
VideoPlayerController.file(File(Provider.of<SendDataModel>(context, listen: false).displayImageVideo()));
videoPlayerListener = () {
if (videoController != null && videoController.value.size != null) {
if (mounted) setState(() {});
videoController.removeListener(videoPlayerListener);
}
};
vcontroller.addListener(videoPlayerListener);
await vcontroller.setLooping(true);
await vcontroller.initialize();
await videoController?.dispose();
if (mounted) {
setState(() {
//saveImagePath = null;
videoController = vcontroller;
});
}
await vcontroller.play();
} //startVideoPlayer
Thanks!
You can call the function from initState(). initState() is called only once when the StatefulWidget is inserted into the Widget tree, so it's a good place to initialize variables or do what you're trying to do.
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
super.initState();
// Do anything you need done here
_startVideoPlayer();
// If you want a slight delay, use Future.delayed
Future.delayed(Duration(seconds: 1), (){
_startVideoPlayer();
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
// rest of app