What kind of changes does "ref.watch(FutureProvider)" detect? - flutter

I'm really confusing that what is ref.watch(authUserFutureProvider);//here below detecting.
When final user = FirebaseAuth.instance.currentUser; // here set appropriately, ref.watch(authUserFutureProvider);//here detect the changes in the provider.
However, if I intentionally make user == null with FirebaseAuth.instance.signOut(); and execute authEmail(ref) with ref.refresh(authEmailFutureProvider);, ref.watch(authUserFutureProvider);//here do not detect any changes and nothing has been done in //do something when ref.watch() detected changes
I wonder why this happen and what kind of changes in FutureProvider should be detected.
Thanks for your helpful advises.
Future<bool> authEmail(ref) async {
try {
final user = FirebaseAuth.instance.currentUser; // here
await user?.sendEmailVerification();
return true;
}on FirebaseAuthException catch (e){
//do somthing
return false
}
//Declared Globally
final authEmailFutureProvider = FutureProvider<bool>((ref) async => authEmail(ref),);
class Test extends ConsumerWidget {
final authC = ref.watch(authUserFutureProvider);//here
authC.when(
//do something when ref.watch() detected changes
)
}
return Scaffold(
body: Padding(
//omit
Align(
child: SizedBox(
width: double.infinity,
child: TextButton(
onPressed: () {
ref.refresh(authEmailFutureProvider);
}
)
//omit
)

Related

How to show loading indicator in simple way?

I'm coding await user?.reload();//here to reload `UserClass ' and during reloading, want to display indicator.
I learned Using FutureProvider-when() method from river_pod or 'FutureBuilder-snapshot` to implement this indicator.
Is these resolve is general or wonder there is more simple way to implement indicator display like this case ?
thanks for your helpful comment.
void currentUserNotNull(User? user, ref) async {
try {
var user = FirebaseAuth.instance.currentUser;
await user?.reload();//here
ref.read(authLoadingProvider.notifier).update((state) => false);
} on FirebaseAuthException catch (e) {
//
}
}
Iam using this method to loading, you can also use flutter spinners also
Try this
showLoaderDialog(BuildContext context){
AlertDialog alert=AlertDialog(
content: new Row(
children: [
CircularProgressIndicator(),
Container(margin: EdgeInsets.only(left: 7),child:Text("Loading..." )),
],),
);
showDialog(barrierDismissible: false,
context:context,
builder:(BuildContext context){
return alert;
},
);
}
I could solve this using flutter_easyloading package like
import 'package:flutter_easyloading/flutter_easyloading.dart';
void currentUserNotNull(User? user, ref) async {
try {
EasyLoading.show(maskType: EasyLoadingMaskType.black, status: "Loading...");
var user = FirebaseAuth.instance.currentUser;
await user?.reload();//here
EasyLoading.dismiss();
} on FirebaseAuthException catch (e) {
//
}
}
but still wonder I should do this or not...

I'm using the Paytm all in one sdk in my flutter application. It's throwing PlatformException error

In my app, in a page I'm calling the startTransaction() plugin method, and storing the response as in the paytm documentation. On recieving response, I want to return the the status whether it was success or failure to previous page. So in init() function I'm calling another async method to startTransaction and check for the response.
PlatformException (0, Unknown error, {response : { response of transaction})
class StartTransaction extends StatefulWidget {
int orderId;
double totalAmount;
PaymentPayload paymentPayload;
bool success;
StartTransaction({this.orderId,this.totalAmount});
#override
_StartTransactionState createState() => _StartTransactionState();
}
class _StartTransactionState extends State<StartTransaction> {
#override
void initState() {
super.initState();
initiateTransaction();
}
Future initiateTransaction() async {
if(widget.success == null){
widget.paymentPayload = await createPaymentGateway(
widget.orderId,
userBloc.userData.username,
widget.totalAmount.toStringAsFixed(2),
context);
var pgResp = AllInOneSdk.startTransaction(
widget.paymentPayload.mid,
widget.orderId.toString(),
widget.totalAmount.toStringAsFixed(2),
widget.paymentPayload.txnToken,
widget.paymentPayload.callbackUrl,
true,
false);
pgResp.then((value) {
print(value);
setState(() {
widget.success = value['RESPCODE'] == 01;
});
}).catchError((onError) {
setState(() {
widget.success = false;
});
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: FutureBuilder(
builder: (context, snapshot) {
if(widget.success == true) {
print('Payment successful');
Navigator.pop(context,true);
} else if(widget.success == false) {
print('Payment unsuccessful');
Navigator.pop(context,false);
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('We are processing your transaction', style: TextStyle(fontSize: 36),),
CircularProgressIndicator(),
],
),
);
}
),
),
);
}
}```
You need to call transaction status API based on the order id and MID used in the transaction. There is no need to call the starttransaction method again
You should validate the transaction response via a server-side request using the Transaction Status API. This API requires checksumhash in request and response. You must verify the Order ID and Amount with your data. The status should be treated as the final status of the transaction in all cases.
You need to use our static callback url in this case
Staging Environment: "https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=<order_id>"
Production Environment: "https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=<order_id>"

call one asynchronous function when the first one runs flutter

I have two asynchronous functions, one returns a popup, the other makes a permission request. I call them in the init method. But they are called simultaneously, i.e. the first window appears and immediately the second. How do I fix this?
class _MyAppState extends State<MyApp> {
final keyIsFirstLoaded = 'is_first_loaded';
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
final context = MyApp.navKey.currentState.overlay.context;
await showDialogIfFirstLoaded(context);
await initPlatformState();
});
}
showDialogIfFirstLoaded(BuildContext context, prefs) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool isFirstLoaded = prefs.getBool(keyIsFirstLoaded);
if (isFirstLoaded == null) {
showDialog(
context: context,
builder: (BuildContext context) {
// return object of type Dialog
return new AlertDialog(
// title: new Text("title"),
content: new Text("//"),
actions: <Widget>[
new FlatButton(
child: new Text(".."),
onPressed: () {
Navigator.of(context).pop();
prefs.setBool(keyIsFirstLoaded, false);
},
),
],
);
},
);
}
}
initPlatformState() async {
print('Initializing...');
await BackgroundLocator.initialize();
print('Initialization done');
final _isRunning = await BackgroundLocator.isRegisterLocationUpdate();
setState(() {
isRunning = _isRunning;
});
onStart();
print('Running ${isRunning.toString()}');
}
add return to showDialog statement, you're not returning a Future so await isn't doing anything
Personal advice: always specify return types, cause if you don't, you get dynamic return type. If you do specify it, the IDE/dart analysis server will help you with problems such as this one.

Getting location data in initState

I need to get location data which is used to calculate the distance between the user and other locations. This is on the app's home page and I don't want to do this every time the page loads, that's why I set up a timestamp and the location is grabbed only if five minutes pass.
What I have now is something like this in the home page:
LocationData _currentPosition;
#override
void initState() {
super.initState();
_getLocationData();
}
_getLocationData() async {
final content = Provider.of<Content>(context.read());
final _timestamp = DateTime.now().millisecondsSinceEpoch;
final _contentTimestamp = content.homeTimestamp;
if ((_contentTimestamp == null) ||
((_timestamp) - _contentTimestamp) >= 300000) {
try {
_locationData = await location.getLocation();
content.homeTimestamp = _timestamp;
setState(() {
_currentPosition = _locationData;
});
} on Exception catch (exception) {
print(exception);
} catch (error) {
print(error);
}
}
}
And I store the timestamp in Provider because I want it to persist when the user leaves the home page and returns. Not sure how to set it up without notifyListeners()
int _homeTimestamp;
int get homeTimestamp => _homeTimestamp;
set homeTimestamp(int newValue) {
_homeTimestamp = newValue;
notifyListeners();
}
My problem is that sometimes the location doesn't get stored and the page doesn't load. Is there a better way to do this?
I was thinking of adding a FutureBuilder in the body, but that would mean that the location will be retrieved every time the user loads the page, or I can just do the timestamp check in the body and not load the FutureBuilder all the time, but that doesn't seem right.
body: _currentPosition == null
? Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 20.0,
width: 20.0,
child: CircularProgressIndicator(),
),
SizedBox(
width: 10.0,
),
Text("Getting your location..."),
],
),
)
: Column(
...
use shared preference to check if the _getLocationData() method is called and use Timer.periodic(); method to call the function every five minutes.

Download, save as, and change background image of the phone with Flutter

I need help regarding the images in my app. I would like to add 3 buttons for:
Download
Save as
Change phone wallpaper
I'm not using urls. I already have my images in an assets repository.
Do you have any idea how I can do that? Thank you.
You can copy paste run full code below
You can use package https://pub.dev/packages/wallpaper_manager
You can directly set wallpaper with image in assets
Example code's assets image path is "assets/tmp1.jpg"
code snippet
result = await WallpaperManager.setWallpaperFromAsset(
assetPath, WallpaperManager.HOME_SCREEN);
working demo
full code
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:wallpaper_manager/wallpaper_manager.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown';
String _wallpaperFile = 'Unknown';
String _wallpaperAsset = 'Unknown';
#override
void initState() {
super.initState();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
String platformVersion;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
platformVersion = await WallpaperManager.platformVersion;
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_platformVersion = platformVersion;
});
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> setWallpaperFromFile() async {
setState(() {
_wallpaperFile = "Loading";
});
String result;
var file = await DefaultCacheManager().getSingleFile(
'https://images.unsplash.com/photo-1542435503-956c469947f6');
// Platform messages may fail, so we use a try/catch PlatformException.
try {
result = await WallpaperManager.setWallpaperFromFile(
file.path, WallpaperManager.HOME_SCREEN);
} on PlatformException {
result = 'Failed to get wallpaper.';
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_wallpaperFile = result;
});
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> setWallpaperFromAsset() async {
setState(() {
_wallpaperAsset = "Loading";
});
String result;
String assetPath = "assets/tmp1.jpg";
// Platform messages may fail, so we use a try/catch PlatformException.
try {
result = await WallpaperManager.setWallpaperFromAsset(
assetPath, WallpaperManager.HOME_SCREEN);
} on PlatformException {
result = 'Failed to get wallpaper.';
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_wallpaperAsset = result;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Column(
children: <Widget>[
RaisedButton(
child: Text("Platform Version"),
onPressed: initPlatformState,
),
Center(
child: Text('Running on: $_platformVersion\n'),
),
RaisedButton(
child: Text("Set wallpaper from file"),
onPressed: setWallpaperFromFile,
),
Center(
child: Text('Wallpaper status: $_wallpaperFile\n'),
),
RaisedButton(
child: Text("Set wallpaper from asset"),
onPressed: setWallpaperFromAsset,
),
Center(
child: Text('Wallpaper status: $_wallpaperAsset\n'),
),
],
)),
);
}
}