moxt

Just another Blog site

FlutterでListViewしたい

   

こんにちは。
陰キャな仮想通貨投資家こと、梅木栽培マンです。

ReactNativeに辟易したので、最近はFlutterを触っています。

スマホアプリといえばListViewですよね。
FlutterでListViewしようとしたときに出てきた疑問と解の雑メモです。

単純なListViewしたい

ドキュメントを読みましょう。
https://docs.flutter.io/flutter/widgets/ListView-class.html

There are three options for constructing a ListView:

The default constructor takes an explicit List of children. This constructor is appropriate for list views with a small number of children because constructing the List requires doing work for every child that could possibly be displayed in the list view instead of just those children that are actually visible.

The ListView.builder takes an IndexedWidgetBuilder, which builds the children on demand. This constructor is appropriate for list views with a large (or infinite) number of children because the builder is called only for those children that are actually visible.

The ListView.custom takes a SliverChildDelegate, which provides the ability to customize additional aspects of the child model. For example, a SliverChildDelegate can control the algorithm used to estimate the size of children that are not actually visible.

つまり、ListView.builderを使いましょうと書いていますね()

『デフォルトのコンストラクタだと子Viewを全部描画しようとするんで、表示する要素数が少ないときに使うといいすよ。』と言ってます。
ドロワーに表示するメニュー一覧とか、ある程度要素数の規模が読めそうなモノに使うのが良さげですね。
一方、ツイートだのフィードだの写真のサムネ一覧みたいな表示しようと思ったらいくらでも出てきちゃうような大量の要素をListView上に展開したい場合は避けたほうがいいでしょう。
『上記のようなケースではListView.builderを使いましょう。』と言ってます。

ListView.customはちょっと何言ってるか分からないです。

ListView.builderはよくあるスマホアプリを作ろうとすると必須なモノなので、これだけ学びます。
ListView.builderの使い方はザックリ下記の通り。

itemBuilderにWidgetを返す関数を渡してやる必要がある。これだけ覚えておけば君はすでにListViewだ。
itemCountはListViewで表示する要素の数。
これを明示的に指定しないと無限なListViewができる。
上の例では予め与えられた_objectListというヤツの要素数を指定してる。

他にもpaddingとかitemExtentとかあるので、興味があればドキュメントを読みましょう。

http通信で取得したJSONデータを使ってListViewしたい

書き方はイケてないけど、ヤリたいこと実現するコードはこんな感じですね。

読めば何したいかなんとなく分かるかと思います(たぶん)。
initState時にClipオブジェクトを取得する処理(_loadClipってヤツね)を呼び出して、setStateで状態を更新してるだけですね。

Flutterで採用されてるDartのことはあんまり知りませんが、シングルスレッドらしいです。
非同期処理はFutureなりStreamsを使いましょう。
今回はhttp通信でJSONデータを取得したいんでFutureを使ってます。(キーボードの入力イベントとかはStreamsかな?たぶん)
非同期処理しようとすると『async』と『await』は必ず使うことになるので、どういうモノかドキュメント読むなりして理解しておくと良さそうです。
FutureのエラーハンドリングはcatchErrorってヤツでデキます。

  • FutureBuilderというWidgetを使うと捗るかもしれませんね
    • https://stackoverflow.com/questions/44645260/how-to-implement-api-calls-in-flutter
    • https://www.youtube.com/watch?v=R2I0osLdjgQ

ページング可能なAPIを使って無限スクロールするListViewしたい

この要件もスマホアプリあるある言いたいですね。
googlingしても見つけられなかったので書いておきます。

前提としてAPI側でページングできるようにしておく必要あります。
その上で下記のようなことをすればinfinite scroll listview in flutterできますね。

  • 『スクロール位置がListViewの底まで来た』を検知できるようにする
  • _loadClipにoffsetを渡して、次に追加すべきClipのリストをゲットする
  • setStateで状態を更新

コードはこんな感じ。

『スクロール位置がListViewの底まで来た』を検知できるようにする

NotificationListener<T extends Notification>というWidgetがあるのでこれを使います。
Tに何入れんの?
今回はスクロールの様子を捕捉したいのでScrollNotificationというヤツを使ってます。

extentAfterの値でスクロールポジションが底か否か判断してます。
他にイケてる方法ありましたら、イケてるエントリー(笑)書いてもらって是非とも本記事を駆逐して欲しいです。

これで『スクロール位置がListViewの底まで来た』を検知できるようになりました。

_loadClipにoffsetを渡して、次に追加すべきClipのリストをゲットする

this._loadClips(this._objectList.length);

これですね。

setStateで状態を更新

更新しましょう。

this._objectList.insertAll(this._objectList.length, x);

insertAll良いですね。

細かい話

無限スクロールをやるために、ローディングしてるか否かフラグ(_isLoading)を追加しています。
で、_loadClip呼ばれたタイミングでフラグ立てて、何回もAPI叩かないようにしてます。
で、『無事にClipのリストを取得した or Die』のタイミングでフラグを落としてます。

なんかナイーブな実装でアレな感じですね…

PullToRefresh(ひっぱり更新)するListViewしたい

RefreshIndicatorというWidgetを使います。

実装例は下記のとおり。
どうでもいいけど、これWidgetのネストがヤバいですね。

onRefreshにやってやりたい処理を書けばOK。
onRefreshのハンドラメソッドではなぜかFutureを返り値として要求してくるので、適当に返すようにしてください。

それからAwesomeApiでFutureを返すように変更してます。
onRefreshで生成したcompleterのcompleteを呼び出したいからです。

他にもListViewのあるある要件いろいろあるので整理して随時更新予定

 - プログラミング

336px




336px




  • このエントリーをはてなブックマークに追加
  • follow us in feedly

  関連記事

ReactなComponent同士を連携させたい

実践的なサンプルに塗れてなんとなく使ってると破綻する。 分かってること、分かってないことを整理しておきたい。 …

no image
GrowthPushのAndroid-SDK(?)のコードを読んでみる

できること、できないことを知るために。 GrowthPush.java …

no image
Rubyのモジュール機能とRailsのHelperについて考える

Moduleとは 参考サイトを見ながら思ったことをメモ …

no image
RubyMine(OSX)でGit操作するときのコマンド集

GITを操作系のポップアップを表示したい

no image
意識低いRuby on Rails再入門2

Modelを作り、コンソール上からデータを追加した。 次はこのデータをlocalhost:3000にアクセスしたときに表示させてみたい。 …

no image
Macでdocker系のコマンドが使えなくなったら確認すること

OSXではdockerは使えないため、別にVMを立ち上げ、そこでdockerを動かしてる。 macからdockerコマンドを使うためにboot2dockerというコマンドを使う。 …

no image
SwiftでOSのバージョンが8.0.0以下とそれより大きいヤツで処理を分岐させたい

前置き push通知のデバイストークン取得方法がiOS8から変わりました。 …

no image
意識低いRuby on Rails再入門3

ActionViewを使ってModelクラスの新規作成画面を作りたい。 ウェブアプリ上でModelのクラスを作成する。 …

no image
ディープラーニングが気になる

ダラダラとメモ。 Contents1 …

no image
iOSアプリの設計ってどうやるの?

ViewControllerに処理を詰め込みすぎて保守が大変になるのはあるあるネタですよね。 じゃあ、ViewControllerでやることってなんだろうって問われると、まあ、こんなんだろうなってフワッとしてる。 …