2021/8/9 : Flutter : Common Flutter errorsの訳

Common Flutter errors

Introduction

This page explains several frequently-encountered Flutter framework errors and gives suggestions on how to resolve them. This is a living document with more errors to be added in future revisions, and your contributions are welcomed. Feel free to open an issue or submit a pull request to make this page more useful to you and the Flutter community.

このページでは、頻繁に発生するいくつかのFlutterフレームワークエラーについて説明し、それらを解決する方法について提案します。 これは、将来の改訂でさらにエラーが追加される生きたドキュメントであり、あなたの貢献を歓迎します。 このページをあなたとFlutterコミュニティにとってより役立つものにするために、issueを開くか、プルリクエストを送信してください。


‘A RenderFlex overflowed…’

RenderFlex overflow is one of the most frequently encountered Flutter framework errors, and you probably have run into it already.

RenderFlexオーバーフローは、最も頻繁に発生するFlutterフレームワークエラーの1つであり、あなたもおそらくすでに経験しているかもしれません。

What does the error look like?

When it happens, you’ll see yellow & black stripes indicating the area of overflow in the app UI in addition to the error message in the debug console:

The following assertion was thrown during layout:
A RenderFlex overflowed by 1146 pixels on the right.

The relevant error-causing widget was
    Row 	    lib/errors/renderflex_overflow_column.dart:23
The overflowing RenderFlex has an orientation of Axis.horizontal.
The edge of the RenderFlex that is overflowing has been marked in the rendering 
with a yellow and black striped pattern. This is usually caused by the contents 
being too big for the RenderFlex.
(Additional lines of this message omitted)

How might you run into this error?

The error often occurs when a Column or Row has a child widget that is not constrained in its size. For example, the code snippet below demonstrates a common scenario:

このエラーは、ColumnまたはRowに、サイズが制限されていない子ウィジェットがある場合によく発生します。 たとえば、以下のコードスニペットは一般的なシナリオを示しています。

Widget build(BuildContext context) {
  return Container(
    child: Row(
      children: [
        Icon(Icons.message),
        Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text("Title", style: Theme.of(context).textTheme.headline4),
            Text(
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed"
                " do eiusmod tempor incididunt ut labore et dolore magna "
                "aliqua. Ut enim ad minim veniam, quis nostrud "
                "exercitation ullamco laboris nisi ut aliquip ex ea "
                "commodo consequat."),
          ],
        ),
      ],
    ),
  );
}

In the above example, the Column tries to be wider than the space the Row (its parent) can allocate to it, causing an overflow error. Why does the Column try to do that? To understand this layout behavior, you need to know how Flutter framework performs layout:

上記の例では、Columnは、Row(Columnの親)が割り当てることができるスペースよりも広くしようとしているため、オーバーフローエラーが発生します。 なぜColumnはそれを行おうとするのですか? このレイアウト動作を理解するには、Flutterフレームワークがレイアウトを実行する方法を知る必要があります。


To perform layout, Flutter walks the render tree in a depth-first traversal and passes down size constraints from parent to child… Children respond by passing up a size to their parent object within the constraints the parent established.” – Flutter architectural overview

「レイアウトを実行するために、Flutterは深さ優先走査でレンダーツリーをウォークし、親から子にサイズ制約を渡します…子は、親が確立した制約内で親オブジェクトにサイズを渡すことによって応答します。」


In this case, the Row widget doesn’t constrain the size of its children, nor does the Column widget.

この場合、Rowウィジェットはその子のサイズを制約(制限)せず、Columnウィジェットも制約(制限)しません。

Lacking constraints from its parent widget, the second Text widget tries to be as wide as all the characters it needs to display.

親ウィジェットからの制約(制限)がないため、2番目のTextウィジェットは、表示する必要のあるすべての文字(長い文章)に必要な幅になろうとします。

 

The self-determined width of the Text widget then gets adopted by the Column which clashes with the maximum amount of horizontal space its parent the Row widget can provide.

次に、Textウィジェットで自己決定された幅がColumnに採用され、その幅が、RowウィジェットがColumnウィジェットに提供する水平方向のスペースの最大値と衝突します。

How to fix it?

Well, you need to make sure the Column won’t attempt to be wider than it can be. To achieve this, you need to constrain its width. One way to do it is to wrap the Column in an Expanded widget:

さて、あなたは、「Columnが可能な範囲を超えて広くなろうとしないこと」を確実にする必要があります。 これを実現するには、その(Columnの)幅を制限する必要があります。 これを行う1つの方法は、ColumnをExpandedウィジェットでラップすることです。

child: Row(
  children: [
    Icon(Icons.message),
    Expanded(
      child: Column(
        // code omitted
      ),
    ),
  ]
)

ExpandedによりColumnの幅が、取りうる最大値(親であるRowの幅)に指定される。指定されるので、Constraints(制限)が無い状態が解消される。

よってエラーが出なくなる、ということ。


Another way is to wrap the Column in a Flexible widget and specify a flex factor.

別の方法としては、ColumnをFlexibleウィジェットでラップして、Flexibleのflex引数を設定する方法があります。

 

In fact, the Expanded widget is equivalent to the Flexible widget with a flex factor of 1.0,

実際、Expandedウィジェットは、flexファクターを1.0に設定したFlexibleウィジェットと同等です。

 

as its source code shows.

ソースコードを見てみましょう。

 

To further understand how to use the Flex widget in Flutter layouts, please check out this Widget of the Week video on the Flexible widget.

FlutterレイアウトでFlexウィジェットを使用する方法をさらに理解するには、FlexibleウィジェットのこのWidget of theWeekビデオを確認してください。

 

Further information:

The resources linked below provide further information about this error.

以下にリンクされているリソースは、このエラーに関する詳細情報を提供します。

参考

https://flutter.dev/docs/testing/common-errors#a-renderflex-overflowed




‘RenderBox was not laid out’

While this error is pretty common, it’s often a side effect of a primary error occurring earlier in the rendering pipeline.

このエラーはかなり一般的ですが、レンダリングパイプラインの初期に発生したプライマリエラーの副作用であることがよくあります。

 

What does the error look like?

どんなエラーですか?

The message shown by the error looks like this:

エラーによって表示されるメッセージは次のようになります。

RenderBox was not laid out: 
RenderViewport#5a477 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE

How might you run into this error?

どのようにしてこのエラーに遭遇する可能性がありますか?

 

Usually, the issue is related to violation of box constraints, and it needs to be solved by providing more information to Flutter about how you’d like to constrain the widgets in question.

通常、この問題はボックス制約の違反に関連しているため、問題のウィジェットをどのように制約するかについて、Flutterに詳細情報を提供することで解決する必要があります。

 

You can learn more about how constraints work in Flutter on the page Understanding constraints.

Flutterで制約(constraints)がどのように機能するかについて詳しくは、制約(constraints)についてのページをご覧ください。

 

The RenderBox was not laid out error is often caused by one of two other errors:

RenderBox was not laid outエラーは、他の2つのエラーのいずれかが原因であることがよくあります。

  • ‘Vertical viewport was given unbounded height’
  • ‘An InputDecorator…cannot have an unbounded width’

参考

https://flutter.dev/docs/testing/common-errors#renderbox-was-not-laid-out




‘Vertical viewport was given unbounded height’

This is another common layout error you could run into while creating a UI in your Flutter app.

これは、FlutterアプリでUIを作成するときに発生する可能性のあるもう1つの一般的なレイアウトエラーです。

 

What does the error look like?

どんなエラーですか?

The message shown by the error looks like this:

エラーメッセージは以下の通りです。

The following assertion was thrown during performResize():
Vertical viewport was given unbounded height.

Viewports expand in the scrolling direction to fill their container. 
In this case, a vertical viewport was given an unlimited amount of 
vertical space in which to expand. This situation typically happens when a 
scrollable widget is nested inside another scrollable widget.
(Additional lines of this message omitted)

How might you run into this error?

どのようにしてこのエラーに遭遇する可能性がありますか?

 

The error is often caused when a ListView (or other kinds of scrollable widgets such as GridView) is placed inside a Column.

このエラーは、ListView(またはGridViewなどの他の種類のスクロール可能なウィジェット)がColumn内に配置する場合によく発生します。

 

A ListView takes all the vertical space available to it, unless it’s constrained by its parent widget.

ListViewは、親ウィジェットによって制約されていない限り、使用可能なすべての垂直方向のスペースを使用します。

 

However, a Column doesn’t impose any constraint on its children’s height by default.

ただし、Columnはデフォルトで、自分の子ウィジェットの高さ(height)に制約を課しません。

 

2つの動作の組み合わせにより、ListViewのサイズを決定できなくなります。(ということでエラーが出る。)

Widget build(BuildContext context) {
  return Center(
    child: Column(
      children: <Widget>[
        Text('Header'),
        ListView(
          children: <Widget>[
            ListTile(
              leading: Icon(Icons.map),
              title: Text('Map'),
            ),
            ListTile(
              leading: Icon(Icons.subway),
              title: Text('Subway'),
            ),
          ],
        ),
      ],
    ),
  );
}

 

How to fix it?

どうやって修正すれば良いですか?

 

To fix this error, specify how tall the ListView should be.

このエラーを修正するには、ListViewの高さを指定する必要があります。

 

To make it as tall as the remaining space in the Column, wrap it using an Expanded widget (see the example below).

Columnの残りのスペースと同じ高さにするには、Expandedウィジェットでラップします(以下の例を参照)。

 

Otherwise, specify an absolute height using a SizedBox widget or a relative height using a Flexible widget.

あるいは、

絶対的な高さ(height)をSizedBoxウィジェットを使って指定する

Flexibleウィジェットを使って相対的な高さ(height)を指定する

などの方法が必要です。

Widget build(BuildContext context) {
  return Center(
    child: Column(
      children: <Widget>[
        Text('Header'),
        Expanded(
          child: ListView(
            children: <Widget>[
              ListTile(
                leading: Icon(Icons.map),
                title: Text('Map'),
              ),
              ListTile(
                leading: Icon(Icons.subway),
                title: Text('Subway'),
              ),
            ],
          ),
        ),
      ],
    ),
  );
}

Further information:

The resources linked below provide further information about this error.

このエラーに関してのさらなる情報

参考

https://flutter.dev/docs/testing/common-errors#vertical-viewport-was-given-unbounded-height




‘An InputDecorator…cannot have an unbounded width’

The error message suggests that it’s also related to box constraints, which are important to understand to avoid many of the most common Flutter framework errors.

エラーメッセージは、ボックスの制約にも関連していることを示しています。これは、最も一般的なFlutterフレームワークエラーの多くを回避するために理解することが重要なものです。

What does the error look like?

The message shown by the error looks like this:

エラーメッセージは以下のようになります。

The following assertion was thrown during performLayout():
An InputDecorator, which is typically created by a TextField, cannot have an 
unbounded width.
This happens when the parent widget does not provide a finite width constraint. 
For example, if the InputDecorator is contained by a `Row`, then its width must 
be constrained. An `Expanded` widget or a SizedBox can be used to constrain the 
width of the InputDecorator or the TextField that contains it.
(Additional lines of this message omitted)

How might you run into the error?

This error occurs, for example, when a Row contains a TextFormField or a TextField but the latter has no width constraint.

このエラーは、たとえば、RowにTextFormFieldまたはTextFieldが含まれているが、後者に幅の制約がない場合に発生します。

Widget build(BuildContext context) {
  return MaterialApp(
    home: Scaffold(
      appBar: AppBar(
        title:
            Text('Unbounded Width of the TextField'),
      ),
      body: Row(
        children: [
          TextField(),
        ],
      ),
    ),
  );
}

 

How to fix it?

As suggested by the error message, fix this error by constraining the text field using either an Expanded or SizedBox widget.

エラーメッセージで示されているように、ExpandedウィジェットまたはSizedBoxウィジェットのいずれかを使用してテキストフィールドを制約(幅を指定する)することにより、このエラーを修正します。

The following example demonstrates using an Expanded widget:

次の例は、Expandedウィジェットを使っています。

  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Unbounded Width of the TextField'),
        ),
        body: Row(
          children: [
            Expanded(
                child: TextFormField()
            ),
          ],
        ),
      ),
    );
  }

参考

https://flutter.dev/docs/testing/common-errors#an-inputdecoratorcannot-have-an-unbounded-width


‘Incorrect use of ParentData widget’

This error is about missing an expected parent widget.

このエラーは、期待される(あるべき)親ウィジェットが欠落していることに関するものです。

 

What does the error look like?

The message shown by the error looks like this:

エラーメッセージは次の通りです。

The following assertion was thrown while looking for parent data:
Incorrect use of ParentDataWidget.
(Some lines of this message omitted)
Usually, this indicates that at least one of the offending ParentDataWidgets 
listed above is not placed directly inside a compatible ancestor widget.
//通常、これは、上にある問題の原因のParentDataWidgetsの少なくとも1つが、互換性のある祖先ウィジェット内に直接配置されていないことを示します。

How might you run into the error?

While Flutter’s widgets are generally flexible in how they can be composed together in a UI, a small subset of those widgets expect specific parent widgets.

Flutterのウィジェットは一般的にUIを構成する方法に関して柔軟性がありますが、いくつかのウィジェットは、特定の親ウィジェットを必要とするものもあります。

 

When this expectation can’t be satisfied in your widget tree, you’re likely to see this error.

ウィジェットツリーでこの期待を満たせない場合、このエラーが表示される可能性があります。

 

Here is an incomplete list of widgets that expect specific parent widgets within the Flutter framework.

以下に、Flutterフレームワーク内の「特定の親ウィジェットを期待するウィジェット」のリストの一部を示します。

Widget Expected parent widget(s)
Flexible RowColumn, or Flex
Expanded (a specialized Flexible) RowColumn, or Flex
Positioned Stack
TableCell Table

左側のウィジェットは、必ず、それぞれ対応する右側のウィジェットの子ウィジェットとして使用する必要がある、ということ。

How to fix it?

The fix should be obvious once you know which parent widget is missing.

どの親ウィジェットが欠落しているかがわかれば、修正は明らかです。(必要なウィジェットを親として追加する。)

参考

https://flutter.dev/docs/testing/common-errors#incorrect-use-of-parentdata-widget




‘setState called during build’

The build method in your Flutter code is not a good place to call setState either directly or indirectly.

Flutterコードのbuildメソッドは、直接または間接的にsetStateを呼び出すのに適した場所ではありません。

 

What does the error look like?

When the error occurs, the following message gets displayed in the console:

エラーが発生すると、コンソールに次のメッセージが表示されます。

The following assertion was thrown building DialogPage(dirty, dependencies: 
[_InheritedTheme, _LocalizationsScope-[GlobalKey#59a8e]], 
state: _DialogPageState#f121e):
setState() or markNeedsBuild() called during build.

This Overlay widget cannot be marked as needing to build because the framework 
is already in the process of building widgets.
(Additional lines of this message omitted)

 

How might you run into the error?

In general, this error occurs when the setState method is called within the build method.

一般に、このエラーは、setStateメソッドがbuildメソッド内で呼び出されたときに発生します。

 

A common scenario where this error occurs is when attempting to trigger a Dialog from within the build method.

このエラーが発生する一般的なシナリオは、buildメソッド内からダイアログをトリガーしようと(出そうと)した場合です。

 

This is often motivated by the need to immediately show information to the user, but setState should never be called from a build method.

これは多くの場合、ユーザーに情報をすぐに表示する必要がある時にやりたくなりますが、setStateをbuildメソッドから呼び出さないでください。

 

Below is a snippet that seems to be a common culprit of this error:

以下は、このエラーの一般的な原因と思われるスニペットです。

culprit:犯人、犯罪者(ここでは「原因」)

Widget build(BuildContext context) {

  // Don't do this. 
  showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text("Alert Dialog"),
        );
      });

  return Center(
    child: Column(
      children: <Widget>[
        Text('Show Material Dialog'),
      ],
    ),
  );
}

You don’t see the explicit call to setState, but it’s called by showDialog.

上記のサンプルではsetStateの明示的な呼び出しはありませんが、showDialog内で呼び出されます。

 

The build method is not the right place to call showDialog because build can be called by the framework for every frame, for example, during an animation.

buildメソッドは、showDialogを呼び出すのに適切な場所ではありません。これは、アニメーション中など、フレームごとにbuildメソッドを呼び出すことができるためです。

frameという単語は基本的に「枠、骨組み」みたいな意味だが、Flutterなどの特にアニメーションなどの話で出てくるframeは「(まんがなどの)コマ」のような意味で、毎秒60フレームの一つ一つのこま(フレーム)のこと。

 

How to fix it?

One way to avoid this error is to use the Navigator API to trigger the dialog as a route.

このエラーを回避する1つの方法は、ナビゲーターAPIを使用してダイアログをルートとしてトリガーすることです。

 

In the example below, there are two pages.

以下の例では、2つのページがあります。

 

The second page has a dialog to be displayed upon entry.

2ページに遷移するときに、ダイアログが表示されます(もう一つページ遷移してそこでダイアログを表示する)

 

When the user requests the second page from clicking on a button on the first page, the Navigator pushes two routes in a row – one for the second page and another for the dialog.

ユーザーが最初のページ(FirstScreen)のボタンをクリックして2番目のページ(‘/second’で指定されているページ)を要求すると、ナビゲーターは2つのルートを続けてプッシュします。1つは2番目のページ用、もう1つはダイアログ用(MyDialog())です。

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Screen'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('Launch screen'),
          onPressed: () {
            // Navigate to the second screen using a named route.
            Navigator.pushNamed(context, '/second');
            // Immediately show a dialog upon loading the second screen.
            Navigator.push(
              context,
              PageRouteBuilder(
                barrierDismissible: true,
                opaque: false,
                pageBuilder: (_, anim1, anim2) => MyDialog(),
              ),
            );
          },
        ),
      ),
    );
  }
}

参考

https://flutter.dev/docs/testing/common-errors#setstate-called-during-build




References

To learn more about how to debug errors, especially layout errors in Flutter, check out the following resources:

エラー、特にFlutterのレイアウトエラーをデバッグする方法の詳細については、次のリソースを確認してください。

 

 

 

コメントを残す

メールアドレスが公開されることはありません。