provider icon indicating copy to clipboard operation
provider copied to clipboard

proxy provider does not update values

Open santosh81066 opened this issue 1 year ago • 6 comments

proxy provider is not updating the values following is my main.dart where I am following the exact docs

  ProxyProvider<Auth, ApiCalls>(

            update: (_, auth, __) => ApiCalls(auth.accessToken)),

and following is another class where I wan to update token

class ApiCalls extends ChangeNotifier {
  final String? token;


  ApiCalls(this.token);

following I am attaching image you can see the response Screenshot 2022-09-09 at 22 34 51

santosh81066 avatar Sep 10 '22 18:09 santosh81066

Hello! Could you share a minimal reproducible example? I can't find what's the issue with the information given.

rrousselGit avatar Sep 11 '22 09:09 rrousselGit

ok I will explain you ..... in main.dart file in multi provider I had added 2 providers one is provider which one is auth class below that I created proxy provider which listen update from auth class and send value to my another class Api Calls where I want to update my token ....you can see in above image Response from restoreAccess token there you will find access_token in response I am trying to send that updated access_token value to apicalls from auth class through constructor and you can see retry started and access token beside it and you can compare clearly the access_token from response and token which I am printing are not matching .....since it is not matching I am getting 401 response below

note: Response is printing from Auth and token is printing from ApiCalls

santosh81066 avatar Sep 11 '22 14:09 santosh81066

Rather than using English, could you share an example?

rrousselGit avatar Sep 11 '22 15:09 rrousselGit

ok I will post my whole code what am I doing following is my main.dart where I am using proxy provider to send updated value through constructor

void main() {
  Provider.debugCheckInvalidValueType = null;
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    //  final auth = Auth();
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (_) => Auth(),
        ),
        ProxyProvider<Auth, ApiCalls>(
            update: (_, auth, __) => ApiCalls(auth.accessToken)),
   
        ChangeNotifierProvider(
          create: (_) => FlutterFunctions(),
        ),
        
      ],
      child: Consumer<Auth>(
        builder: (context, value, _) {
          return MaterialApp(
              title: 'Flutter Demo',
              theme: ThemeData(
                
                primarySwatch: Colors.red,
              ),
              home: value.isAuth
                  ? const AdminScreen()
                  : FutureBuilder(
                      future: value.tryAutoLogin(),
                      builder: (context, snapshot) =>
                          snapshot.connectionState == ConnectionState.waiting
                              ? CircularProgressIndicator()
                              : const AdminLoginScreen(),
                    ));
       
        },
      ),

following is my Auth Provider where I want to send updated token to my Apicalls class

class Auth extends ChangeNotifier {

  String? accessToken;
  DateTime? accessTokenExpiryDate;

  String? get token {
    if (accessTokenExpiryDate != null &&
        accessTokenExpiryDate!.isAfter(DateTime.now()) &&
        accessToken != null) {
      return accessToken;
    } else if (accessTokenExpiryDate!.isBefore(DateTime.now())) {
      return accessToken;
    }
    return null;
  }

  Future<void> restoreAccessToken() async {
    print('restoreAccessToken started');

    //print(token);
    final url = '${Ninecabsapi().urlHost}${Ninecabsapi().login}/$sessionId';

    var response = await http.patch(
      Uri.parse(url),
      headers: {
        'Content-Type': 'application/json; charset=UTF-8',
        'Authorization': accessToken!
      },
      body: json.encode(
        {"refresh_token": refreshtoken},
      ),
    );
    var userDetails = json.decode(response.body);

    if (response.statusCode == 401) {
      print(userDetails['messages']);
    }

    sessionId = userDetails['data']['session_id'];
    accessToken = userDetails['data']['access_token'];
    accessTokenExpiryDate = DateTime.now().add(
      Duration(seconds: userDetails['data']['access_token_expiry']),
    );
    refreshToken = userDetails['data']['refresh_token'];
    refreshTokenExpiryDate = DateTime.now().add(
      Duration(seconds: userDetails['data']['refresh_token_expiry']),
    );
    final userData = json.encode({
      'sessionId': sessionId,
      'refreshToken': refreshToken,
      'refreshExpiry': refreshTokenExpiryDate!.toIso8601String(),
      'accessToken': accessToken,
      'accessTokenExpiry': accessTokenExpiryDate!.toIso8601String()
    });
    //print(userDetails);
    print("this is from restoreAcessToken :$userDetails");
    notifyListeners();
    final prefs = await SharedPreferences.getInstance();

    prefs.setString('userData', userData);
    reset();
  }


following is my ApiCalls where I want to update token whenever my token changes in AuthClass

class ApiCalls extends ChangeNotifier {
  final String? token;

  ApiCalls(this.token);


  Future<void>sample(BuildContext context, String sampleType) async {
    print('postVehicles:$token');

    var data = {"vehicletype": vehicleType, "filename": vehicleType};
    Map<String, String> obj = {"attributes": json.encode(data).toString()};

    var flutterFunctions =
        Provider.of<FlutterFunctions>(context, listen: false);
    final url = Ninecabsapi().urlHost + Ninecabsapi().getvehicle;
    try {
      loading();
      var response = http.MultipartRequest("POST", Uri.parse(url))
        ..files.add(await http.MultipartFile.fromPath(
            "imagefile", flutterFunctions.imageFile!.path,
            contentType: MediaType("image", "jpg")))
        ..headers['Authorization'] = token!
        ..fields.addAll(obj);
      final client = RetryClient(
        http.Client(),
        retries: 2,
        when: (response) {
          return response.statusCode == 401 ? true : false;
        },
        onRetry: (req, res, retryCount) async {
          //print('retry started $token');

          if (retryCount == 0 && res?.statusCode == 401) {
            // Only this block can run (once) until done
            await Provider.of<Auth>(context, listen: false)
                .restoreAccessToken();
            req.headers['Authorization'] = token!;
  
            print('retry started ${req.headers['Authorization']}');
            //req.headers.clear();

          }
        },
      );
      final send = await client.send(response);
      final res = await http.Response.fromStream(send);
      switch (res.statusCode) {
        case 201:
          Future.delayed(Duration.zero)
              .then((value) => showsnackbar(context, "Vehicle type inserted"));
      }
      var messages = json.decode(res.body);

      loading();

      //notifyListeners();
    } catch (e) {
      print(e);
    }
  }

 
}

santosh81066 avatar Sep 11 '22 16:09 santosh81066

Hello again! This example isn't something I can execute. Could you update it to something I can run?

rrousselGit avatar Sep 12 '22 09:09 rrousselGit

ok I will mail you my project so that you can run

santosh81066 avatar Sep 12 '22 14:09 santosh81066

problem solved

santosh81066 avatar Sep 25 '22 04:09 santosh81066