RSS2.0

Flutter ver 0.3.2 の、無限スクロールする GridView のサンプル

『The Infinite ListView』等で Google 検索すると無限スクロールする ListView については情報がえられるのですが、同じようなことを GridView でやっているサンプルは見つからなかったので書いておきます。言うならば、The Infinite GridView のサンプルです。Flutter は ver 0.3.2 を利用しています。
infinite_scroll_gridview.png
無限スクロールに関しては、やっていることは無限スクロール ListView と同じです。なので GridView のサンプルではありますが、同じ方法論で無限スクロール ListView も作ることができます。

機能としては、以下を実装しています。
・GridView を末尾までスクロールすると、次のデータを新たに作成して追加表示する
・GridView の要素は、表示されるタイミングで構築(遅延構築)される
・GridView の要素は 1 列で 3 個ずつ並べられる

以下がサンプルコードになります。
import 'package:flutter/material.dart';

void main() => runApp(new InfiniteGridViewSampleWidget());

/// 無限にスクロールする GridView サンプルの StatefulWidget
class InfiniteGridViewSampleWidget extends StatefulWidget {
  @override
  InfiniteGridViewSampleState createState() =>
      new InfiniteGridViewSampleState();
}

/// 無限にスクロールする GridView サンプルの State
class InfiniteGridViewSampleState extends State<InfiniteGridViewSampleWidget> {
  // 表示するデータの List。
  // 初期値としてデータを 20 件いれておく。
  final List<int> items = new List.generate(20, (index) => index);

  // GridView を構築して返す。
  // この GridView を末尾までスクロールした場合、表示するデータ件数を増やして追加表示できるようにする。
  //
  // GridView が末尾までスクロールされたかは、GridView に設定した ScrollController によって検知できる。
  //
  // GridView に表示される要素の最大数は、GridView が構築された時点で固定される。
  // そのため、表示するデータ件数を増やすには、再度 GridView を再構築する必要がある。
  @override
  Widget build(BuildContext context) {
    // GridView のスクロールを検知するための ScrollController。
    final ScrollController _scrollController = new ScrollController();
    // ScrollController にイベントリスナーを設定する。
    _scrollController.addListener(() {
      // 最後までスクロールしたら、次のデータを読み込む。
      if (_scrollController.position.maxScrollExtent <=
          _scrollController.position.pixels) {
        // 表示するデータを追加し、ウィジェットを再構築するよう通知する。
        setState(() {
          // 表示するデータにさらに 20 件データを追加する。
          this.items.addAll(
              new List.generate(20, (index) => this.items.length + index));
        });
      }
    });

    // GridView の要素を表示されるタイミングで構築できるように itemBuilder を指定する。
    return new MaterialApp(
      home: new Scaffold(
        // itemBuilder を指定できる GridView.builder() で GridView を構築する。
        body: GridView.builder(
          itemBuilder: (BuildContext context, int index) {
            // itemBuilder は、引数 index の位置にある GridView の要素が表示されるタイミングで
            // 呼び出され、その要素を構築して返す。

            print("make item: ${index}");

            // 引数 index の位置にある GridView の要素を構築して返す。
            return new Center(child: new Text("#${index}"));
          },
          // GridView で表示するデータの件数を設定する。
          // これ以上の件数のデータを表示する場合、新たな itemCount 値を設定して GridView を再構築する必要がある。
          itemCount: items.length,
          // スクロールされたことを検知するため、ScrollController を設定する。
          controller: _scrollController,
          // GridView の要素は横に 3 個ずつ並べてレイアウトする。
          // これは、new GridView.count(crossAxisCount: 3, children: <Widget>[]) に相当する。
          // GridView の要素の配置は SliverGridDelegateWithFixedCrossAxisCount を設定することで指定できる。
          gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 3,
          ),
        ),
      ),
    );
  }
}

続きを読む FlutterDart  コメント (0)  2018/05/17 19:11:40

Dart 非同期処理の async / await について

Flutter でのアプリ開発にあたって Dart 言語を順序立って体系的に学ぶ余裕がなかったこともあり、必要になるポイント毎に言語仕様を調べていました。しかし、とうとう非同期処理で利用される await キーワードの動作について納得できない事象に遭遇し、きちんと調べ直すことにしました。今日は調べ直した Dart 言語の非同期処理について書いてみたいと思います。

事の発端: await をつけているのに処理が進んでしまう

Dart には await というキーワードがあり、非同期処理を行うメソッドの呼び出し時に追記することで、メソッド内部の非同期処理の完了を待つことができます。
以下のように書いた場合、sumNumber() メソッドの内容が非同期処理であっても、返り値を i で受け取るまで、その先に処理は進みません。
var i = await sumNumber();
これについては Dart の言語仕様を正しい理解したものですが、await をとりまく言語仕様について、もう少し考慮しなければならない点がありました。

例えば以下のようなコードを実行すると、どのように標準出力されるでしょうか。
import 'dart:async';

main() {
  ready();
  countDown();
  go();
}

void ready() {
  print("Ready set...");
}

void countNumber(number) {
  print(number);
}

void countDown() async {
  // ここで await を使って待機したい
  await countNumber(3);
  countNumber(2);
  countNumber(1);
}

void go() {
  print("Go!!");
}

await で処理が止まるので、
Ready set...
3
2
1
Go!!
となりそうですが、実際には以下のように出力されます。
Ready set...
Go!!
3
2
1
上記ソースコードからのこの出力結果が納得できない方が今回の対象読者です。私もこの記事を書くまで納得できませんでした。
続きを読む FlutterDart  コメント (0)  2018/05/14 20:09:51

VMwarePlayer で動かした Fedora 26 で KVM を動かしてみる

諸事情により VMwarePlayer で利用している Fedora 26 の中で、さらに KVM を動かせたので方法を残しておきます。
KVM を使いたい理由はマイブームの Flutter 開発で、Android エミュレーターを高速に動かすためです。Linux の Android エミュレーターって、HXAM(Intel Hardware Accelerated Execution Manager) の代わりに KVM を使うと高速化できるそうなのです。
バーチャルマシンの中でバーチャルマシンを動かすという 2 重入れ子なんてとてもパフォーマンスが出ないだろうと思っていたのですが、KVM を有効化しない場合に比べれば結構早く動くようになったので、試してみてよかったです。

前提として、物理マシンや一層めの VMwarePlayer で、HXAM や KVM を有効にしておきましょう。
物理マシンについては BIOS の設定で、VMwarePlayer についてはゲストのバーチャルマシンの CPU の設定で有効にできます。

Fedora 26 に KVM をインストールする

KVM を使うとはいえ、qemu や libvirt も組み合わせて使う必要があるので以下のパッケージを入れておきます。
# dnf install -y qemu-kvm virt-manager virt-install

更に、バーチャルマシンを入れ子にして使う場合のパフォーマンスを上げるため、カーネルモジュールの Nested KVM を有効にします。

以下のコマンドで現在の Nested KVM の設定を確認できます。
# cat /sys/module/kvm_intel/parameters/nested 
N
N(無効)になっているので、これを Y(有効)にしていきます。
設定ファイル /etc/modprobe.d/qemu-system-x86.conf に "options kvm_intel nested=1" を追記します。
設定ファイルを読み込むため、一度カーネルモジュールを外して再度読み込みます。カーネルモジュールは modprobe コマンドでロード/アンロードすることができます。
# echo "options kvm_intel nested=1" >> /etc/modprobe.d/qemu-system-x86.conf
# modprobe -r kvm_intel 
# modprobe kvm_intel 
カーネルモジュール kvm_intel を再ロードしたら、Nested KVM の設定を確認してみます。
# cat /sys/module/kvm_intel/parameters/nested 
Y
Y(有効)になりました。

virt-manager でバーチャルマシンを管理する

これは Android エミュレーターを使う話ではなく、普通にバーチャルマシンとして他の OS を使う話になります。

KVM でのバーチャルマシンの管理には、libvirt で提供される virt-manager を使うと便利です。
virt-manager を実行するユーザーを libvirt グループに所属させておくと、su 権限なしで実行できるそうなので、グループに所属させておきます。
# gpasswd -a momokan libvirt

あとは virt-manager コマンドを叩けば virt-manager を起動できます。
$ virt-manager 

Android エミュレーターを起動する

KVM を有効にして Android エミュレーターを動かすには、Android エミュレーターに KVM を有効化するオプションを渡す必要があります。
昔の Android Studio では Android エミュレーターを起動する際にこのオプションを指定できたようなのですが、現在の AVD Manager には設定項目が見当たりません。なので、一度 AVD Manager で作った Android エミュレーターを、Android SDK の emulator コマンドで起動します。
$ emulator -avd Pixel_API_27 -qemu -m 1024 -enable-kvm &
Pixel_API_27 というのが私が作った Android エミュレーターの名前です。-enable-kvm オプションを指定することで、KVM を有効にして起動することができます。
ちなみに -m オプションは端末のメモリ量(MB)です。ついでに指定しておいたもので KVM の有効化とは関係ありません。
  Linux  コメント (0)  2018/05/10 18:58:37

ImageMagick6 を Fedora 26 にインストールする

諸事情により Fedora 26 で ImageMagick を使える環境を用意することになりました。
普通だったら yum install して終わりなのですが、リポジトリに上がっているのはインストールしたい ImageMagick6 ではなく、ImageMagick7 のようでした。
なのでソースからビルドしてみたいと思います。

jpg, png モジュールをインストールする

ImageMagick6 本体をビルドしただけでは、取り扱う画像フォーマットが限定されています。jpg や png を扱えない…というより、ほとんどの画像フォーマットが使えないようです。画像フォーマットのデコーダー等は ImageMagick 本体には含まれておらず、自分で用意してくれということなのだと思います。画像フォーマットのライセンスやらもいろいろ事情がありそうです。

そこで、ImageMagick6 をビルドする際に必要な画像フォーマットのパッケージをインストールしておきます。
以下は jpg, png に関するパッケージです。devel パッケージもインストールしておくことに注意してください。
# yum install libjpeg libjpeg-devel
# yum install libpng libpng-devel

Wand の画像フォーマットエラー

jpg, png に関するパッケージをインストールしておかないと、いざ ImageMagick6 を使おうとした時にエラーになります。
python から ImageMagick6 を使える Wand では、以下のようなエラーが発生します。
Traceback (most recent call last):
  File "wandtest.py", line 4, in <module>
    with Image(filename='sample.jpg', format='JPEG') as img:
  File "/home/momokan/python/wand/wand/image.py", line 2744, in __init__
    self.read(filename=filename, resolution=resolution)
  File "/home/momokan/python/wand/wand/image.py", line 2822, in read
    self.raise_exception()
  File "/home/momokan/python/wand/wand/resource.py", line 222, in raise_exception
    raise e
wand.exceptions.MissingDelegateError: no decode delegate for this image format `JPEG' @ error/constitute.c/ReadImage/504
Exception TypeError: TypeError("object of type 'NoneType' has no len()",) in <bound method Image.__del__ of <wand.image.Image: (empty)>> ignored

ImageMagick6 をインストールする

ソースコードは github に上がっています。なのでこれを持ってきましょう。
$ git clone https://github.com/ImageMagick/ImageMagick6
そうしたら clone した ImageMagick6 ディレクトリに移動し、configure, make, make install します。
この辺りのビルドの仕方は伝統的な C プログラムですね。
$ cd ImageMagick6
$ ./configure
$ make
# make install
configure のオプションにインストールディレクトリなんかもあるはずなのですが、面倒なので特に指定していません。指定しない場合には /usr/local/lib に共有ライブラリ(.so ファイル)がインストールされます。
続きを読む WEB 技術python  コメント (0)  2018/05/07 16:41:26

Macbook を快適な開発環境にするために

最近 Flutter で使うことが多いので。
基本 Linux 使いなので Linux の使い心地に寄せてます。

iOS の設定

ファンクションキーを通常のファンクションキーとして使う

システム環境設定 > キーボード にて、
「F1、F2 などのすべてのキーを標準のファンクションキーとして使用」を選択する
バックライトの明るさや音量を調節する場合は「fn」キーを押しながらそのキーを押す

ターミナルの設定

ターミナルでのカーソルの移動速度を早くする

システム環境設定 > キーボード にて、 「キーのリピート」、「リピート入力認識時間」で速度を調整する

ターミナル起動時に .bashrc を読み込む

.bash_profile に以下を追記する
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

ターミナルのビープ音を消す

環境設定 > プロファイル > 詳細 > ベル にて、「オーディオベル」のチェックを外す


  コメント (0)  2018/04/28 19:04:00

Flutter の showModalBottomSheet() のサンプル

先週触り始めた Flutter (バージョン 0.2.8) ですが、ModalBottomSheet と呼ばれるウィジェットを使うのに苦労したので、動いたコードをサンプルとして載せて置こうと思います。

ModalBottomSheet はスマホの画面の底辺から上に向かってにょきっと出てくるダイアログの一種です。Android や iPhone で文字を入力しようとした時に出てくるキーボードみたいなやつです。
以下のスクリーンショットを見てもらうとイメージしやすいと思います。これが今回のサンプルコードの実行結果です。
flutter_showModalBottomSheet1.pngflutter_showModalBottomSheet2.png
もともと表示されていたウィジェットに重ねて表示されること、画面下からスライドして表示されること、スマホのディスプレイの形状にかかわらず、上辺以外が埋め尽くされた形のダイアログになっていることが特徴です。3 点めの、上辺以外が埋め尽くされた形のダイアログであることが特にユニークな特徴で、最近の iPhone のようにディスプレイの下辺の角が丸まっていたりすると、普通のダイアログウィジェットでは高さを最大にしても角が丸まっている領域まで広がらないのです。非矩形なダイアログを作ることができないのでしょうね。

続きを読む FlutterDart  コメント (0)  2018/04/25 16:41:09

Flutter / Dart 言語で Android 用開発環境を構築する

Flutter は Google 製のハイクオリティな UI フレームワークです。Android と iOS の 2 つのプラットフォームで同時に開発ができ、そのため使用言語は Java でも Swift でもなく、Dart という言語になります。クロスプラットフォーム開発という点では以前試した Ionic 2 と同じようなコンセプトにも聞こえますが、Ionic 2 と異なりネイティブアプリの開発を前提としているようです。

ハイクオリティというからにはどのくらいハイクオリティなのか試してやろうということで、今回は開発環境の構築からアプリを起動するところまでをやってみたいと思います。
ちなみに開発環境はいつもどおり Fedora 26 64bit 版です。なので iOS でアプリを動かすのはいったんおいておいて、Android アプリを起動するところまでがゴールとなります。公式サイトに環境毎の開発環境構築手順が載っているので、Linux 用のドキュメントをベースに進めてみます。

Flutter の開発環境を構築する

Flutter での開発環境を構築するには、Flutter の他に Android や iOS の開発環境も準備しておく必要があります。
冒頭に記載したとおり、今回は Android アプリを動かすことを目標としているので、Android Studio を使って Android 版の開発環境だけを作っていきます。

Flutter をインストールする

それでは Flutter からインストールしていきます。
公式サイトからLinux 用 Flutterをダウンロードし、展開します。現時点での最新バージョンは 0.2.8-beta でした。
$ wget https://storage.googleapis.com/flutter_infra/releases/beta/linux/flutter_linux_v0.2.8-beta.tar.xz
$ tar xf flutter_linux_v0.2.8-beta.tar.xz
# mv flutter /usr/local/
ここでは展開した flutter を /usr/local 配下に配置しています。
続きを読む FlutterDart  コメント (0)  2018/04/19 13:24:41

npm リポジトリを verdaccio で構築する

前回 npm パッケージを作ってみましたが、npm でパッケージを作っていくとそれをリポジトリに公開したくなってきます。NodeJs には https://www.npmjs.com/ という公式リポジトリが存在しますが、一般公開したくない npm モジュールを置きたいとか、npm リポジトリ自体も自分で構築したいという要望もあるでしょう。
自前の npm リポジトリサーバーはいくつか存在するのですが、今回は構築の簡単な verdaccio を使ってみようと思います。

dotall-user.png

verdaccio のインストールする

npm リポジトリ用のサーバーにログインし、verdaccio をインストールします。
npm モジュールとして提供されているので、npm コマンドでインストールできます。
# npm install --global verdaccio
verdaccio をインストールしたマシンをそのままサーバーとして使うので、--global を指定してグローバル環境にインストールします。
私の環境では /usr/lib/node_modules/verdaccio/ 配下にインストールされました。

続いて verdaccio を起動します。
$ verdaccio &
verdaccio は root 権限がいらないそうなので、一般ユーザーで起動します。

これで verdaccio の npm リポジトリにアクセスできるようになっています。
verdaccio を動かしているマシンの DNS を verdaccio.example.com とした場合、アクセス URL は http://verdaccio.example.com:4873 です。
続きを読む WEB 技術JavaScript  コメント (0)  2018/04/12 20:06:02

npm でパッケージ管理された JavaScript 開発をしてみる

ある程度の規模の開発をしていくと、避けては通れないのが共通ロジックのパッケージ化と、どのパッケージを利用するかという依存性の管理です。Java には maven や gradle, Python には pip や setuptools があるように、JavaScript ではしばらく前から npm が利用されています。npm は Node.js が提供するパッケージ管理ツールで、Node.js 自体を利用しない JavaScript 開発でも十分に利用価値があります。自分で書いたコードをパッケージ化することでロジックの共有や使い回しが簡単になりますし、自分のロジックが利用している他パッケージのバージョン管理をすることで動作の保証やパッケージのバージョンアップを厳密に行えるようになります。
dotall.png
今回はこの npm コマンドを使って、既に提供されているライブラリを依存関係を管理しつつ利用していこうと思います。

ちなみに npm ではパッケージとモジュールという用語が定義されています。
内容をかいつまむと、npm パッケージは package.json と呼ばれるファイルとプログラムを配置したディレクトリのこと、npm モジュールは require 構文によって他のソースコードから読み込まれるライブラリのことです。自分が開発するものが npm パッケージ、他のエンジニアが開発したものが npm モジュールという感じでしょうか。主体が変わることで呼び方が変わるわけですね。

npm をインストールする

いつもどおり yum コマンドで npm をインストールしましょう。
# yum install npm
これで終わりです。
続きを読む JavaScript  コメント (0)  2018/04/10 19:20:00

Java で Akka Stream を遊んでみる

Akka Stream は並列/分散処理を実現するためのライブラリのひとつです。他のライブラリ同様に、処理全体をいくつかの処理単位に分割し、複数箇所に独立して存在するマシンで並列に処理することができますが、Akka Stream は大きな特徴として、その処理単位を扱うバッファスペースを固定長(bounded buffer space)として実現しているという点があります。

普通、分散処理では独立したマシン同士が処理データや処理結果を共有するためにメッセージ送信をしあうのですが、そこで課題となるのが受取ったメッセージの保管方法です。処理するデータを受け取ったとしても、自分の担当する処理内容が他よりも時間のかかる内容だった場合、受け取ったデータを捌ききれずに滞留してしまうことになります。このため、受け取ったデータの保管する領域を可変長にしてすべて保管できるようにしたり(この場合、保管領域が無尽蔵に必要となってしまう)、固定長の領域に補完しきれない分は捨ててしまったり(データの消失がありうる)といった手段が取られることがあります。

しかし Akka Stream は、いくつかの工夫によって、処理単位を扱う領域であるバッファスペースを固定長としたまま、持ちきれなかったデータを捨てることなくメッセージングを実現しています。

今回は最初ということで、Akka Stream の立ち入った話には触れずに公式ドキュメントの Java 向け Quickstart Guide の内容をさらってみたいと思います。
2 年前の年末くらいに一度触っていたのですが、それからバージョンが上がって使い勝手が良くなっているようなので、その辺の調査も兼ねた感じですね。
続きを読む Akka Stream  コメント (0)  2018/02/16 17:18:54
プロフィール HN: ももかん
ゲーム作ったり雑談書いたり・・・していた時期が私にもありました。
カレンダー
<<2018, 7>>
1234567
891011121314
15161718192021
22232425262728
2930311234