重构时无法提取对封闭类方法的引用

Posted

技术标签:

【中文标题】重构时无法提取对封闭类方法的引用【英文标题】:Reference to an enclosing class method cannot be extracted on refactoring 【发布时间】:2020-04-25 10:53:36 【问题描述】:

当我想做“提取到小部件”时,它会引发错误:“无法提取对封闭类方法的引用”

我知道有一些变量必须从类构造函数中获取它们的数据,但我希望 android Studio 提取小部件,然后我会纠正错误的代码,比如 Visual Studio 没有任何错误,然后将代码提取到新的小部件它需要将新提取的小部件复制到新的 dart 文件中并更正错误。

我想提取 Card 小部件部分。

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),
                        ),
                ),
              );
            );
  

【问题讨论】:

【参考方案1】:

只需使用“提取方法”而不是“提取小部件”。 VSCode 将添加所有返回和引用。

编辑:如果您只想使用“提取小部件”,只需将该小部件包装在容器中,然后在该小部件上使用“提取小部件”。 如果这不起作用,请在小部件中注释掉 setState() 函数,然后重试。

【讨论】:

我们可以使用 Extract 方法或手动提取小部件,但是在使用提取方法或提取小部件时有什么约定吗?抱歉,我是 Flutter 的新手 :)【参考方案2】:

您的 deleteTx 可能包含一个 setState(() ) 方法,请尝试注释您调用 deleteTx 的代码部分,并在提取后将其放回。

【讨论】:

【参考方案3】:

我遇到了同样的问题,就我而言,这是因为 ListView.builder 和你一样。

所以很容易修复,只需在 Widget build 中创建一个类并返回 Card 并在 ListView.builder 中返回它TransactionList 类 带有所需的参数。

【讨论】:

【参考方案4】:

你必须关心一些事情:

    无论何时提取小部件,该小部件都不应包含当前工作页面中使用的任何变量。 所有函数或方法都应该是参数化的。

【讨论】:

【参考方案5】:

这是因为您在 Card 小部件中从封闭类(即 TransactionList)引用了一个变量(例如,transactions)。在这种情况下,提取的最佳方法可能是在您的类之外创建无状态/有状态小部件并剪切 Card 小部件并将其粘贴为您创建的该小部件的构建方法的返回类型。您可以使用您创建的小部件的构造函数来引用这些变量。

【讨论】:

【参考方案6】:

如果您可以注释掉代码中的“deleteTx(transactions[index].id)”部分,然后使用“onPressed: ()”,您将能够提取到小部件。提取后可以使用 onPressed: ()setState(() deleteTx(transactions[index].id););

【讨论】:

【参考方案7】:

当前类中的变量可能存在一些局部引用,因此如果存在一些引用,我们无法从那里提取小部件。

【讨论】:

【参考方案8】:

将 onpressed 等属性转换为 cmets,然后重试“提取小部件”并继续

【讨论】:

【参考方案9】:

您可以使用“提取方法”。这是一个简单的方法。 VSCode 将添加所有返回和引用。

【讨论】:

以上是关于重构时无法提取对封闭类方法的引用的主要内容,如果未能解决你的问题,请参考以下文章

Java Lambda 引用封闭对象:替换为私有静态类?

重构改善既有代码

设计模式

如何处理 TDD 的重构阶段

内部类成员从封闭类的可访问性

如何从封闭的外部类调用与匿名类中实现的方法同名的方法?