How to call Two APIs in a Single Function

I want to get the data from database. I have 2 Apis 1: to get records information like name, address, company etc… another one api 2: for getting ProfilePhoto. I am getting output from first api but not able to get profilePhoto Api. So how can I call both Apis in a single function? function is

Future<DataDetails> getData1() async {
    var id = 34;

    final response1 = await http.get(Uri.parse("Api Url"));

    if(response1.statusCode == 200) {

      var temp = DataDetails.fromJson(jsonDecode(response1.body));
      print(temp);
      return temp;
    }

    return DataDetails.fromJson(jsonDecode(response1.body)) ;
}

FutureBuilder(
                 future: getData(),
                  builder: (context, snapshot) {
                    return Screenshot(
                              controller: _ssController,
                              child: GestureDetector(
                                onTap: () {
                                  Navigator.push(context, MaterialPageRoute(builder: (context) => OntapView()));
                                },
                                child: Stack(
                                  children: [
                                    Container(
                                      padding: const EdgeInsets.all(10),
                                      width: 350,
                                      decoration: BoxDecoration(
                                          borderRadius: BorderRadius.circular(15),
                                          // color: Colors.amber[100]
                                          color: const Color(0xffccf7ff)
                                      ),
                                      child:  Column(
                                        children: [
                                          Container(
                                            padding: EdgeInsets.all(10),
                                            child: Row(
                                              children: [
                                                Container(
                                                  height: 15,
                                                  width: 200,
                                                  child: Text('${snapshot.data!.cardName} ',
                                                    style: TextStyle(fontWeight: FontWeight.bold),),
                                                ),
                                     SizedBox(height: 8),
                                          Row(
                                            crossAxisAlignment: CrossAxisAlignment.start,
                                            mainAxisAlignment: MainAxisAlignment.start,
                                            children: [
                                              CircleAvatar(
                                                radius: 45,
                                                backgroundColor: Colors.grey,
                                                backgroundImage: FileImage(File('${snapshot.data!.profilePhotoPath}')),        
                                              ),
                                              const SizedBox(width: 10),
                                              Container(
                                                  padding: const EdgeInsets.only(left: 20,top: 10),
                                                  width: 130,
                                                  height: 100,
                                                  child: Column(
                                                    mainAxisAlignment: MainAxisAlignment.start,
                                                    children: [
                                                      Text('${snapshot.data!.name} ',
                                                        style: const TextStyle(fontSize: 22,fontWeight: FontWeight.bold),),
                                                      const SizedBox(height: 5),
                                                      Container(
                                                        child: Text('${snapshot.data!.address}',
                                                          style: const TextStyle(fontSize: 12),),
                                                      )
                                                    ],
                                                  )
                                              ),

I am new to flutter. If possible please share example code.

To combine the two API calls into a single function in Flutter, you can use the Future.wait method. This allows you to wait for multiple futures to complete and gather their results. Below is an example of how to implement this in your code.

Example Code

Here’s how you can modify your getData1 function to fetch data from both APIs and return a combined result:

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

class DataDetails {
  final String cardName;
  final String profilePhotoPath;
  final String name;
  final String address;

  DataDetails({required this.cardName, required this.profilePhotoPath, required this.name, required this.address});

  factory DataDetails.fromJson(Map<String, dynamic> json) {
    return DataDetails(
      cardName: json['cardName'],
      profilePhotoPath: json['profilePhotoPath'],
      name: json['name'],
      address: json['address'],
    );
  }
}

Future<DataDetails> getData() async {
  var id = 34;

  // Fetch data from both APIs
  final response1 = await http.get(Uri.parse("Api Url 1"));
  final response2 = await http.get(Uri.parse("Api Url 2"));

  if (response1.statusCode == 200 && response2.statusCode == 200) {
    var dataDetails = DataDetails.fromJson(jsonDecode(response1.body));
    // Assuming the second API returns the profile photo URL or path
    dataDetails.profilePhotoPath = jsonDecode(response2.body)['profilePhoto'];

    return dataDetails;
  }

  // Handle error if needed
  throw Exception('Failed to load data');
}

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FutureBuilder<DataDetails>(
      future: getData(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return CircularProgressIndicator();
        } else if (snapshot.hasError) {
          return Text('Error: ${snapshot.error}');
        } else if (!snapshot.hasData) {
          return Text('No data found');
        }

        return Screenshot(
          controller: _ssController,
          child: GestureDetector(
            onTap: () {
              Navigator.push(context, MaterialPageRoute(builder: (context) => OntapView()));
            },
            child: Stack(
              children: [
                Container(
                  padding: const EdgeInsets.all(10),
                  width: 350,
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(15),
                    color: const Color(0xffccf7ff),
                  ),
                  child: Column(
                    children: [
                      Container(
                        padding: EdgeInsets.all(10),
                        child: Row(
                          children: [
                            Container(
                              height: 15,
                              width: 200,
                              child: Text(
                                '${snapshot.data!.cardName}',
                                style: TextStyle(fontWeight: FontWeight.bold),
                              ),
                            ),
                            SizedBox(height: 8),
                            Row(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              mainAxisAlignment: MainAxisAlignment.start,
                              children: [
                                CircleAvatar(
                                  radius: 45,
                                  backgroundColor: Colors.grey,
                                  backgroundImage: snapshot.data!.profilePhotoPath.isNotEmpty
                                      ? FileImage(File(snapshot.data!.profilePhotoPath))
                                      : null, // Handle case where there is no image
                                ),
                                const SizedBox(width: 10),
                                Container(
                                  padding: const EdgeInsets.only(left: 20, top: 10),
                                  width: 130,
                                  height: 100,
                                  child: Column(
                                    mainAxisAlignment: MainAxisAlignment.start,
                                    children: [
                                      Text(
                                        '${snapshot.data!.name}',
                                        style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
                                      ),
                                      const SizedBox(height: 5),
                                      Container(
                                        child: Text(
                                          '${snapshot.data!.address}',
                                          style: const TextStyle(fontSize: 12),
                                        ),
                                      ),
                                    ],
                                  ),
                                ),
                              ],
                            ),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        );
      },
    );
  }
}

Key Changes Explained

  1. Single Function to Fetch Data:
  • The getData function now makes both API calls sequentially.
  • After fetching the data from both APIs, it updates the profilePhotoPath in the DataDetails instance based on the response from the second API.
  1. Error Handling:
  • If either API call fails, an exception is thrown. You can handle this in the FutureBuilder to show an error message.
  1. Using FutureBuilder:
  • The FutureBuilder listens for the result of the combined API call and updates the UI accordingly, handling loading and error states.

Notes

  • Ensure your API URLs are correct.
  • Adjust the parsing logic based on the actual response structure from your APIs.
  • This approach assumes that you want to call both APIs sequentially. If you need them to run concurrently, consider using Future.wait, but this may require additional handling for the results.

Feel free to reach out if you have any more questions or need further assistance!