flutterdartstate-management

Using Api and provider together


I am calling Get api for name and date in my profile header and also patch Api in my update profile screen now i want to use provider for upadating name immediately in my profile header now how can i use get api and provider in my profile header ??


class ProfileHeader extends StatelessWidget {
  const ProfileHeader({super.key});
  @override
  Widget build(BuildContext context) {
    final profileProvider = Provider.of<ProfileProvider>(context);

    return Container(
      width: MediaQuery.of(context).size.width * 0.9,
      padding: const EdgeInsets.all(40.0),
      decoration: BoxDecoration(
        color: Colors.green,
        borderRadius: BorderRadius.circular(16),
      ),
      child: Row(
        children: [
          const CircleAvatar(
            radius: 40,
            backgroundImage: AssetImage('assets/images/image.png'),
          ),
          const SizedBox(width: 16),
          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                profileProvider.name,
                style: const TextStyle(
                  color: Colors.white,
                  fontSize: 20,
                  fontWeight: FontWeight.bold,
                ),
              ),
              const SizedBox(height: 4),
              Text(
                'Last Login: ${profileProvider.lastLogin}',
                style: const TextStyle(color: Colors.white, fontSize: 13),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

Provider

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

class ProfileProvider with ChangeNotifier {
  String _name = 'Loading...';
  String _lastLogin = 'Loading...';

  String get name => _name;
  String get lastLogin => _lastLogin;

  Future<void> fetchProfile() async {
    const String url = 'https://api.vezigo.in/v1/app/profile';
    final prefs = await SharedPreferences.getInstance();
    final accessToken = prefs.getString('accessToken');

    try {
      final response = await http.get(
        Uri.parse(url),
        headers: {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer $accessToken',
        },
      );

      if (response.statusCode == 200) {
        final Map<String, dynamic> jsonResponse = json.decode(response.body);
        _name = jsonResponse['data']['name'];
        _lastLogin = jsonResponse['data']['createdAt'];
        notifyListeners();
      } else {
        throw Exception('Failed to load profile');
      }
    } catch (error) {
      _name = 'Error';
      _lastLogin = 'Error';
      notifyListeners();
    }
  }

  Future<void> updateProfile(String newName, String newEmail) async {
    const String url = 'https://api.vezigo.in/v1/app/profile';
    final prefs = await SharedPreferences.getInstance();
    final accessToken = prefs.getString('accessToken');

    try {
      final response = await http.patch(
        Uri.parse(url),
        headers: {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer $accessToken',
        },
        body: json.encode({
          'name': newName,
          'email': newEmail,
        }),
      );

      if (response.statusCode == 200) {
        final responseBody = json.decode(response.body);

        _name = responseBody['data']['name'];
        notifyListeners();

        await prefs.setString('name', _name);
        await prefs.setString('email', responseBody['data']['email']);
      } else {
        throw Exception('Failed to update profile');
      }
    } catch (error) {
      print('Error updating profile: $error');
    }
  }
}

I tried but in my profile header in both name and date there is showing loading .. enter image description here


Solution

  • You initialized profileProvider, but are not using it. You can use WidgetsBinding.instance.addPostFrameCallback to fetch profile once the widget is built.

     Widget build(BuildContext context) {
        final profileProvider = Provider.of<ProfileProvider>(context);
    
        WidgetsBinding.instance.addPostFrameCallback((_) {
          profileProvider.fetchProfile();
        });
    

    and use the Text widget to display:

    Text(
        profileProvider.name,
        style: const TextStyle(
            color: Colors.white,
            fontSize: 20,
            fontWeight: FontWeight.bold,
        ),
    ),
    

    Additionally, I'm guessing you already added the provider to your main:

    ChangeNotifierProvider(
          create: (context) => ProfileProvider(),