質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

1回答

4717閲覧

Flutter: TextEditingControllerの処理で無限ループが発生する

massanmesu

総合スコア36

Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2021/06/25 00:56

TextEditingControllerの使い方を学ぶため、Flutterの公式サイトからコードをコピペしAndroid studioで実行したところ、TextFormFieldをタップした瞬間に無限ループが発生しました。
イメージ説明

/// Flutter code sample for TextEditingController // This example creates a [TextField] with a [TextEditingController] whose // change listener forces the entered text to be lower case and keeps the // cursor at the end of the input. import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); /// This is the main application widget. class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); static const String _title = 'Flutter Code Sample'; @override Widget build(BuildContext context) { return const MaterialApp( title: _title, home: MyStatefulWidget(), ); } } /// This is the stateful widget that the main application instantiates. class MyStatefulWidget extends StatefulWidget { const MyStatefulWidget({Key? key}) : super(key: key); @override State<MyStatefulWidget> createState() => _MyStatefulWidgetState(); } /// This is the private State class that goes with MyStatefulWidget. class _MyStatefulWidgetState extends State<MyStatefulWidget> { final TextEditingController _controller = TextEditingController(); // 中身が更新されると呼ばれる関数。ここで無限ループしてる? @override void initState() { super.initState(); _controller.addListener(() { final String text = _controller.text.toLowerCase(); _controller.value = _controller.value.copyWith( text: text, selection: TextSelection(baseOffset: text.length, extentOffset: text.length), composing: TextRange.empty, ); }); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Container( alignment: Alignment.center, padding: const EdgeInsets.all(6), child: TextFormField( controller: _controller, decoration: const InputDecoration(border: OutlineInputBorder()), ), ), ); } }

console

1Syncing files to device sdk gphone x86 arm... 2W/IInputConnectionWrapper(24578): beginBatchEdit on inactive InputConnection 3W/IInputConnectionWrapper(24578): endBatchEdit on inactive InputConnection 4I/TextInputPlugin(24578): Composing region changed by the framework. Restarting the input method. 5W/IInputConnectionWrapper(24578): getTextBeforeCursor on inactive InputConnection 6W/IInputConnectionWrapper(24578): getSelectedText on inactive InputConnection 7W/IInputConnectionWrapper(24578): getTextAfterCursor on inactive InputConnection 8I/TextInputPlugin(24578): Composing region changed by the framework. Restarting the input method. 9I/TextInputPlugin(24578): Composing region changed by the framework. Restarting the input method. 10W/IInputConnectionWrapper(24578): getTextBeforeCursor on inactive InputConnection 11W/IInputConnectionWrapper(24578): getSelectedText on inactive InputConnection 12W/IInputConnectionWrapper(24578): getTextAfterCursor on inactive InputConnection 13W/IInputConnectionWrapper(24578): getTextBeforeCursor on inactive InputConnection 14W/IInputConnectionWrapper(24578): getSelectedText on inactive InputConnection 15W/IInputConnectionWrapper(24578): getTextAfterCursor on inactive InputConnection 16I/TextInputPlugin(24578): Composing region changed by the framework. Restarting the input method. 17W/IInputConnectionWrapper(24578): getTextBeforeCursor on inactive InputConnection 18W/IInputConnectionWrapper(24578): getSelectedText on inactive InputConnection 19W/IInputConnectionWrapper(24578): getTextAfterCursor on inactive InputConnection 20I/TextInputPlugin(24578): Composing region changed by the framework. Restarting the input method. 21W/IInputConnectionWrapper(24578): getTextBeforeCursor on inactive InputConnection 22W/IInputConnectionWrapper(24578): getSelectedText on inactive InputConnection 23W/IInputConnectionWrapper(24578): getTextAfterCursor on inactive InputConnection 24I/TextInputPlugin(24578): Composing region changed by the framework. Restarting the input method. 25W/IInputConnectionWrapper(24578): getTextBeforeCursor on inactive InputConnection 26...

同じような処理文が規則性なく発生している状況です。

入力した文字列を小文字化してカーソルを最後尾に移動させる、という処理内容だと認識してます。

公式の本文にはリスナー内の処理(今回の場合は_controller.addListener(){} )で無限ループが発生する可能性があるため注意が必要、という旨の文章があるのですが、サンプルがすでに無限ループが発生しているため、解決方法がわかりません。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

例えばですが、下記のようにイベントを無視するフラグ入れたらどうなりますか?

クラスのメンバに追加

dart

1bool _triggerEvents = true;

リスナーのコードを変更

dart

1 _controller.addListener(() { 2 if (!_triggerEvents) return; // イベントを処理するかどうかのフラグ 3 final String text = _controller.text.toLowerCase(); 4 5 // イベントを一時的に聞かないように設定 6 _triggerEvents = false; 7 8 // 値を変更 9 _controller.value = _controller.value.copyWith( 10 text: text, 11 selection: 12 TextSelection(baseOffset: text.length, extentOffset: text.length), 13 composing: TextRange.empty, 14 ); 15 16 // イベントを再度聞き始める 17 _triggerEvents = true; 18 });

こういう感じで試してみてください。でも実際僕なら下記のように書くかもしれません。(実際には検証していません)

dart

1// 下記のようなメソッドを追加 2void modifyText(Function(TextEditingController ctrl) func) { 3 _triggerEvents = false; 4 func(_controller); 5 _triggerEvents = true; 6}

リスナーのコードを変更

dart

1 _controller.addListener(() { 2 if (!_triggerEvents) return; // イベントを処理するかどうかのフラグ 3 final String text = _controller.text.toLowerCase(); 4 5 modifyText((ctrl) => ctrl.text = 'abc' /* このメソッド内はイベントトリガーされない */ ); 6 modifyText((ctrl) => ctrl.text = 'test' /* なんども使うことができる */ ); 7 // ctrl.value も同じです 8 });

書き方は色々ありますので、いい方法がありましたらお教えください。フラグは使わず、都度リスナーを外して追加し直すこともできますね。

投稿2021/06/28 06:57

編集2021/06/28 07:13
hiroshihorie

総合スコア192

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問