flutterasynchronousfuture

waiting for an aync function in flutter is going wrong


I'm having problems waiting for a Future result. I have a function that returns a Future, I call it using await function, but the result I get back is always null even though the debug says it isn't null. This is all driven by the click of a button.

First the button:

new FilledButton(
    child: Text('Copy ${Config.dance}'),
    onPressed: () async
    {
      NamePos? np = await DancePage.getDanceName (context, dance.name + " - Copy", dance.numDancers, dance.numMusicians) ;
      if (np != null && np.name.isNotEmpty && np.numPos > 0)
      {
        // Make a copy of the position names
        List<String> pos = List<String>.filled(np.numPos + np.numMusicians, "") ;
        for (int i = 0 ; i < np.numPos ; ++i)
        {
          if (i < dance.numDancers)
            pos[i] = dance.positionsNames[i] ;
          else
            pos[i] = (i + 1).toString() ;
        }
        int m = 1 ;
        int p = dance.numDancers ;
        for (int i = np.numPos ; i < pos.length ; ++i, ++m, ++p)
        {
          if (p < dance.numPositions)
            pos[i] = dance.positionsNames[p] ;
          else
            pos[i] = "Musician " + m.toString() ;
        }
        // Create a new dance based on the source one
        Dance? nd = await DBServer.instance.addDance(np.name, np.numPos, pos, dance.note);
        if (nd != null)
        {
          // copy dancer positions
          debugPrint ("Copying dancers") ;
          for (Dancer a in Dancer.allDancers(true, Dancer.sBoth))
          {
            if (a.canDoDance (dance.id))
            {
              DancePositions pos = new DancePositions(nd.numPositions) ;
              List<int> can = a.getPositions (dance.id)!.getAllPositions () ;
              for (int p = 0 ; p < nd.numPositions && p < dance.numPositions ; ++p)
              {
                if (can[p] > 0)
                {
                  pos.setPosition(p, can[p]) ;
                }
              }
              a.setPositions(nd.id, pos) ;
              await DBServer.instance.addDancerPositions(a, nd.id);
            }
          }
        }
        else
          debugPrint ("addDance returned null") ;
        Dance.notify() ;
        Navigator.of(context).pop(null);
      }
    }),

The bit that is going wrong is the call to addDance. This always prints the debug "addDance returned null"

This is the addDance function:

Future<Dance?> addDance (String name, int numDancers, List<String> positions, String note) async
{
  debugPrint ("Add dance $name") ;
  Database db = (await database)! ;
  await db.transaction((txn) async
  {
    var raw = await txn.rawInsert('INSERT INTO dances (name, numPlaces, active, note) VALUES (?,?,?,?)', [name,numDancers,1,note] ) ;
    int id = raw.toSigned(64);
    if (id > 0)
    {
      StringBuffer sql = new StringBuffer ("INSERT INTO positions (dance, position, name) VALUES ") ;
      bool first = true ;
      for (int i = 0 ; i < positions.length ; ++i)
      {
        if (first)
          first = false ;
        else
          sql.write (", ") ;
        sql.write ("($id,$i,'") ;
        sql.write (positions[i]) ;
        sql.write ("')") ;
      }
      // debugPrint (sql) ;
      await txn.rawInsert (sql.toString ()) ;
      Dance d = new Dance (id, name, numDancers, true, note) ;
      d.positionsNames = positions ;
      debugPrint ("Created dance id $id") ;
      d == null ? debugPrint ("dance null") : debugPrint ("dance not null") ;
      return d ;
    }
    else
      return null ;
  }) ;
  return null ;
}

The debug I get looks something like:

I/flutter (14661): Created dance id 36
I/flutter (14661): dance not null
D/InsetsController(14661): show(ime(), fromIme=true)
I/flutter (14661): addDance returned null

Can anyone suggest what I'm doing wrong?


Solution

  • I think you're missing a return here:

    await db.transaction((txn) async
    

    So while your transaction closure returns a result, the top-level code in addDance doesn't return that to the caller.

    To fix that:

    return await db.transaction((txn) async