46

While I am passing value from home page to source page it shows an error: The argument type 'Future' can't be assigned to the parameter type 'void Function()'. (argument_type_not_assignable at [strong text] lib\home.dart:15)

Where I am doing wrong??

Home page -

import 'package:flutter/material.dart';
import 'sourceScreen.dart';

class Home extends StatefulWidget {
  int value;
  Home({this.value});
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FlatButton(
          onPressed: Navigator.push(context, MaterialPageRoute(builder: (context)=>SourceScreen({value:value}))), child: null,
        ),
      ),
    );
  }
}

Below page is where I wanna use home page value-

import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'models/model.dart';
import 'models/card.dart';
import 'article.dart';

final API_KEY = '***';

Future<List<Source>> fetchNewsSource() async {
  final response = await http.get(
      'https://newsapi.org/v2/sources?language=en&country=in&apiKey=$API_KEY');

  if (response.statusCode == 200) {
    List sources = json.decode(response.body)['sources'];
    return sources.map((source) => new Source.formJson(source)).toList();
  } else {
    throw Exception('Fail to load data');
  }
}

class SourceScreen extends StatefulWidget {
  @override
  _SourceScreenState createState() => _SourceScreenState();
}

class _SourceScreenState extends State<SourceScreen> {
  var list_source;
  var refreshKey = GlobalKey<RefreshIndicatorState>();

  @override
  void initState() {
    super.initState();
    refreshListSource();
  }

  Future<Null> refreshListSource() async {
    refreshKey.currentState?.show(atTop: false);
    setState(() {
      list_source = fetchNewsSource();
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Color.fromRGBO(58, 66, 86, 1.0),
        appBar: AppBar(
          elevation: 1.0,
          backgroundColor: Color.fromRGBO(58, 66, 86, 1.0),
          title: Text('uTTerNews'),
        ),
        body: Center(
          child: RefreshIndicator(
              child: FutureBuilder<List<Source>>(
                future: list_source,
                builder: (context, snapshot) {
                  if (snapshot.hasError) {
                    Text('Error: ${snapshot.error}');
                  } else if (snapshot.hasData) {
                    List<Source> sources = snapshot.data;
                    return new ListView(
                        children: sources
                            .map((source) =>
                            GestureDetector(
                              onTap: () {
                                Navigator.push(context, MaterialPageRoute(
                                    builder: (context) =>
                                        articleScreen(source: source,)));
                              },
                              child: card(source),
                            ))
                            .toList());
                  }
                  return CircularProgressIndicator();
                },
              ),
              onRefresh: refreshListSource),
        ),
      ),
    );
  }
}
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
mdhv_kothari
  • 627
  • 1
  • 7
  • 14

4 Answers4

156

Replace

onPressed: Navigator.push(...)

with

onPressed: () => Navigator.push(...)

If you need to use await keyword, you can do

onPressed: () async {
  await Navigator.push(...);
  await anyOtherMethod();
}
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
  • 4
    Thanks! But why does this work? Can you explain it? – Petro Mar 07 '20 at 13:51
  • 18
    @Petro `Navigator.push` returns a `Future` and `onPressed` accepts `void`, which is why you can't directly assign `Navigator.push` to `onPressed`, however when you do `onPressed: () => ` You're simply executing `Navigator.push(...)` inside the callback provided by `onPressed`. Hope that explained! – CopsOnRoad Mar 07 '20 at 14:05
  • 3
    Ah, I see thanks for running through that much appreciated! – Petro Mar 07 '20 at 14:14
9

This one worked for me in latest versions

 onPressed: () {
          selectHandler();
 },
Arun Prasad E S
  • 9,489
  • 8
  • 74
  • 87
  • 1
    It doesn't have to do anything with the latest or older versions. This code is essentially equal to `onPressed: selectHandler`. – CopsOnRoad Apr 01 '21 at 11:39
  • 1
    @CopsOnRoad It does. With the latest version, OnPressed: selectHandler doesn't work to onPressed as you can't assign void directly. with onPressed: () => selectHandler you are instructing to execute the function inside the callback. – Sesha Kiran May 19 '21 at 01:39
  • 1
    @SeshaKiran Can you show some code to support your statement that `onPressed: selectHandler` wouldn't work? The only time you may run into the error is when you invoke a method on an object which hasn't been initialized yet (for example when you use `late` keyword for lazy initialization). – CopsOnRoad May 19 '21 at 07:47
  • @CopsOnRoad There was not usage of late keyword, but it was not working for me in a simple case. it was a sample learning code without any API. – Arun Prasad E S May 19 '21 at 11:07
  • @ArunPrasadES A code will be appreciated. – CopsOnRoad May 19 '21 at 11:22
  • @CopsOnRoad Pls. find the code. I added as another answer. – Sesha Kiran Jun 02 '21 at 01:46
4
    @CopsOnRoad -- Here is the sample code that is working for me.

    
      @override
      Widget build(BuildContext context) {
        return Container(
          width: double.infinity,
          child: RaisedButton(
            color: Colors.grey,
            textColor: Colors.black,
            child: Text('Answer 1'),
            **onPressed: () => selectHandler()**,
          ),
        );
      }
    }
    
   
Arun Prasad E S
  • 9,489
  • 8
  • 74
  • 87
Sesha Kiran
  • 199
  • 1
  • 4
  • 1
    First this is not a code I can reproduce on my own. Please post a minimal reproducible code. Second, `Function` is not recommended to be used without the parameter. It should be `Function()` – CopsOnRoad Jun 02 '21 at 06:41
0

simply change the final Function selectHandler to final VoidCallback selectHandler;