'Reference to an enclosing class method cannot be extracted on refactoring

When I want to do "Extract to widget", it raises an error : "reference to an enclosing class method cannot be extracted"

I know there is some variables that must get their data from class constructor but I want Android studio to extract the widget then, I will correct the mistaken codes, like Visual Studio that without any error extract the code to a new widget then it needs to copy the new extracted widget to a new dart file and correct the mistakes.

I want to extract the Card widget part.

import 'package:flutter/material.dart';
import 'package:flutter/material.dart' as prefix0;
import 'package:intl/intl.dart';
import '../model/transaction.dart';

class TransactionList extends StatelessWidget {
  final List<Transaction> transactions;
  final Function deleteTx;

  TransactionList(this.transactions, this.deleteTx);

  @override
  Widget build(BuildContext context) {
    return transactions.isEmpty
        ? LayoutBuilder(
            builder: (ctx, constraint) {
              return Column(
                children: <Widget>[
                  Text(
                    'There is no transaction',
                    style: Theme.of(context).textTheme.title,
                    textDirection: prefix0.TextDirection.rtl,
                  ),
                  SizedBox(
                    height: 10,
                  ),
                  Container(
                      height: constraint.maxHeight * 0.6,
                      child: Image.asset(
                        'assets/images/yalda.png',
                        fit: BoxFit.cover,
                      ))
                ],
              );
            },
          )
        : ListView.builder(
            itemCount: transactions.length,
            itemBuilder: (ctx, index) {
              return **Card**(
                margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 5),
                elevation: 5,
                child: ListTile(
                  leading: CircleAvatar(
                    radius: 30,
                    child: Padding(
                      padding: const EdgeInsets.all(8),
                      child: FittedBox(
                          child: Text('\$${transactions[index].amount}')),
                    ),
                  ),
                  title: Text(
                    transactions[index].title,
                    style: Theme.of(context).textTheme.title,
                  ),
                  subtitle: Text(DateFormat.yMMMd()
                      .format(transactions[index].date)
                      .toString()),
                  trailing: MediaQuery.of(context).size.width > 360
                      ? FlatButton.icon(
                          onPressed: () => deleteTx(transactions[index].id),
                          icon: const Icon(Icons.delete),
                          label: const Text('Delete'),
                    textColor: Theme.of(context).errorColor,
                  )
                      : IconButton(
                          icon: const Icon(Icons.delete),
                          color: Theme.of(context).errorColor,
                          onPressed: () => deleteTx(transactions[index].id),
                        ),
                ),
              );
            });
  }
}


Solution 1:[1]

Simply use "Extract Method" instead of "Extract Widget". VSCode will add all the returns and references.

Edit: If you want to use "Extract Widget" only then simply wrap that widget in a Container and then use "Extract Widget" on that widget. If that doesn't work, comment out setState() function inside the widget and try again.

Solution 2:[2]

Your deleteTx might contain a setState(() {}) method, try to comment that part of your code where you're calling deleteTx it and just put it back after your extraction.

Solution 3:[3]

I had the same issue and in my case it was because of ListView.builder as yours.

So it is easy to fix, Simply make a class and return Card in Widget build and return it in ListView.builder inside the TransactionList class with the desired arguments.

Solution 4:[4]

You have to care about a few things:

  1. Whenever you are extracting a widget, that widget should not contain any variable which is used in the current working page.
  2. All the functions or methods should be parametric.

Solution 5:[5]

It is because you are referencing a variable(for example, transactions) in your Card widget from the enclosing class i.e. TransactionList. The best way to extract in this case could be to just make stateless/stateful widget outside your class and cut the Card widget and paste it as the return type of the build method of that Widget you created. And you can reference those variables using the constructor of that widget you created.

Solution 6:[6]

If you can comment out "deleteTx(transactions[index].id)" parts of your code and then use "onPressed: (){}", you will be able to extract to widget. After the extraction you can use onPressed: (){setState(() {deleteTx(transactions[index].id);});}

Solution 7:[7]

transform onpressed etc. property to comments and then try again 'Extract Widget' and go on

Solution 8:[8]

there might be some local referance to the variable in the current class,so if there some referance we cant extract a widget from there.

Solution 9:[9]

You can use the "Extract Method". It's a simple way. VSCode will add all the returns and references.

Solution 10:[10]

Just remove or comment the setState() from your widget and it gonna works.