(´ワ`)

主に技術系備忘録、たまに日記。

トラックパッドを使わずVimライクにキーボード操作するための方法を模索しています

最近Vimmerになりましたnnsnicoです。
Vimの良さを知ったのは春のインターンシップでメンターの方がIdeaVimを使用していたことがきっかけでした。ターミナルいじりが若干の趣味になりつつあるこの頃でしたので、興味本位でVimを触ってみたところ指をチャカチャカ動かさずにタイピングできることの良さにハマりました!!!!

そんなこんなでVimにハマりすぎた僕は思います。「他のアプリもVimですべて済ませてぇなぁ」と。
その方法を探しています。

現状の僕の環境は以下の感じです

アプリケーションの起動

  • Alfred
    • 言わずとしれたランチャーアプリ。Spotlightよりもシンプルで見やすいのでこちらを使用しています
    • アプリの切り替えもすべてこれに頼っています()

ブラウザー

  • VivaldiSurfingKeysのエクステンションをつけています。
    • vimライクにブラウザ操作ができるのでちょ〜快適
      • hjklで画面のスクロール、yyでページURLのコピー、vでビジュアルモード、f,Cでリンクの指定、ogでgoogle検索、bでブックマーク検索などなど
    • Chromeのエクステンションで動くので、Chromeでも可

エディター

プラグインなど設定は僕のdotfiles内にあります

github.com

もっといろんなアプリをVimっぽく操作したいんだYO

これだけでも十分満足なんですが、欲を言うとブラウザ以外にもっともっと他のアプリもすべてVimライクな操作で解決できる方法を探しています。例えばシステム設定画面の操作を十字キーじゃなくhjklでやるみたいな。
KarabinerのVim風keybindingなども試してみましたがモードの切替の反応が微妙に悪かったのでやめました...
Vimのキーバインディングを行うアプリもいろいろ試しましたがSurfingKeysと競合しあってカオスな挙動を見せたりしてんほぉぉってなった

汎用的にVim風で操作できて一部のアプリでは機能を無視してくれる。そんなキーバインディングアプリがあれば最強なんだけどなぁ。まあSurfingKeysを使うのやめたらすぐに解決できる話なんだけど

FlutterとReactNativeを両方使った感想をお話しする

どうも。@nnsnicoです。
今週末にAndroid関連のLT会があるのでその資料を作る前にどんなことを話そうかを整理する目的でここに話すことを書いておきます。

はじめに

最近(?)なにかと流行っているのではないかという感じのクロスプラットフォームアプリのフレームワーク。わざわざAndroidiOSで書き分けなくても、1つのプログラミング言語で同じもの作れるなんてすごくない?と思って興味を持ち始めました。
フレームワーク自体はたくさんあるのですがどれがどういった良さ悪さを持っているのかはさっぱりだし、文献がすくねぇ(日本語で書いてあるものはおろか英語も公式コミュニティしか盛り上がってない)からいざ試そうにも試しにくい

今回お話しすることはそんな数あるフレームワークの中でもまあまあよさげあさげなFlutterとReactNativeを使ってUIも機能もほぼ同じのアプリを作ってみた感想をメリットとデメリットを添えてお話しすることで少しでも触ってもらえるきっかけになってもらえればと思います。
全く知らない人向けにお話しするので、両フレームワークの簡単な説明もします。

つくったもの

なるべく実用性があると興味がわきやすいと思ったので、API通信を行ってデータを表示するシンプルなものを作ることを目標にしました。
今回はQiita API v2を使用しました。

主な仕様としては、

  • Home画面に新規投稿順で記事がリスト表示される
  • リストを押すと記事の詳細へ遷移して記事の内容がマークダウンで表示される
    • タイトルはCoordinatorLayoutのようにToolbarが伸びたり縮んだりする

よくある感じのアプリです。

Flutterについて

FlutterはGoogleが開発するクロスプラットフォームで動くフレームワークです。Googleが開発しているだけあって、マテリアルデザインを採用した部品を階層的に組み込んでいくコーディングが特徴です。開発言語は同じくGoogleが開発しているDartという言語です。DartはざっくりいうとJavaみたいなJavaScriptです。詳しくは以下を見てください。

Dart programming language | Dart

Flutter - Beautiful native apps in record time

ReactNative

ReactNativeはfacebookが開発するフレームワークです。もともとはReact.jsというWebのフレームワークだったのですが、それをネイティブ向けに作り直したものです。なので書いているコードはReact.jsです。開発言語はJavaScriptです。
JavaScriptであれば動くのでJavaScriptにクロスコンパイルするaltJSでも基本できます。よくある例だとTypeScriptで開発する人はいたりします。僕もします。いい意味でヤバイ人とかだとScala.jsとかで開発を試みた人もいることを聞いたことがあります。Flutterの開発言語であるDartもaltJSなので動くかもしれないです。React.jsはあるみたいです。活発じゃないみたいですが

React Native · A framework for building native apps using React

https://github.com/cleandart/react-dart

Flutterでつくる

Flutterでつくります。ソースコードは以下にあります。

github.com

開発にあたって、@konifarさんのdroidkaigi2018のFlutterアプリを参考にしました。そちらのソースコードも添えて見てみるといいかもしれません。

github.com

全部解説するとすごい長文になるので、特徴をかいつまんで説明します。
Flutterはレイアウト、ボタン、テキストなどの部品を階層ごとに並べて描画します。また、それらの部品は大きく分けて状態を持つ部品(StatefulWidget)と持たざる部品(StatelessWidget)に分けます。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'QiitaMitsukeTatter',
      theme: themeData,
      home: MyHomePage(title: 'Home'),
    );
  }
}

StatefulWidgetはStatefulWidgetの他に、その状態をStateで持つ必要があります。widget.〜でStatefulWidgetが持つstateを得ることができます。

class MyListItem extends StatefulWidget {
  MyListItem({Key key, @required this.topic}) : super(key: key);

  final Topic topic;  // state

  @override
  _MyListItem createState() => _MyListItem();
}

class _MyListItem extends State<MyListItem> {
  @override
  Widget build(BuildContext context) {
  return Container(
      child: ListTile(
        leading: CircleAvatar(
          backgroundImage: (widget.topic.user.imageUrl != null)
              ? NetworkImage(widget.topic.user.imageUrl)
              : null,
        ),
  ...

また、ThemeDataクラスを各コンポーネントに埋め込むことでそのまんまそのカラーが埋め込まれます

import 'package:flutter/material.dart';

final ThemeData themeData = ThemeData(
  brightness: Brightness.light,
  primaryColor: Colors.lightGreen,
  primaryColorBrightness: Brightness.dark,
  accentColor: Colors.indigoAccent,
  dividerColor: Colors.grey[300],
  backgroundColor: Colors.grey[100],
  secondaryHeaderColor: Colors.white,
);

primariColorとかaccentColorをここで選択できるのが良いですね このような描画される部品たちはカタログとして公式が載せているので大変やさしいです

Material Components Widgets - Flutter

プロジェクトの中も少し解説します。Flutterのプロジェクトは/lib配下にメインのソースコードがあります。ライブラリを追加したいときはpubspec.yaml内のdependenciesにぶち込めばいいです。 ディレクトリの階層も単純です。APIの呼び出しをscreen -> repository -> apiと介して呼び出し、結果のJsonをmodelに入れ、screenでmodelを見て描画するだけとなっています。今回のアプリでは特別なアーキテクチャを使ったわけではありませんが、Reduxなどのサポートもされているようです。
Flutterのすこし不便な点は、部品すべてがマテリアルデザインに凝っちゃうのでiOSマテリアルデザインにしたくない時は採用しにくいです

ReactNativeでつくる

ReactNativeでつくります。ソースコードは以下にあります。

github.com

プロジェクトのメインは/src配下にあります。ライブラリなどはpackage.json内です。 アーキテクチャはRedux + Redux-sagaを使用しました。この辺のお話はしないつもりです。

主要な画面たちはcomponents配下にあります。Androidエンジニアの方々だと、Viewの書き方がXMLライクなので親しみがあるかもしれません。

FlatListでデータをリスト描画しています。

class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Home',
  };

  render() {
    const { pressListItem, topics } = this.props.screenProps;
    return (
      <View>
        <StatusBar
          backgroundColor="#689F38FF"
          barStyle="light-content"
        />
        <FlatList
          data={topics}
          extraData={topics}
          keyExtractor={(item, index) => String(index)}
          renderItem={({ item }) => (
            <ListItem
              item={item}
              pressListItem={pressListItem}
            />
          )}
        />
      </View>
    );
  }

もともとがWebのフレームワークなだけあって、FlexCSS(ライクのもの)をViewとして扱うことができます。Androidの場合だと、ライブラリを追加しないと使うことができないのでありがたいです

const styles = StyleSheet.create({
  header: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    backgroundColor: '#8BC34AFF',
    overflow: 'hidden',
    justifyContent: 'flex-end',
    alignItems: 'flex-start',
  },
  ...

  fill: {
    flex: 1,
  },
  ...

ReactNativeの不便な点は、Flutterと違って複雑なViewだと見にくいコードになりがちなことです。今回のコードのDetailScreenが一番の例かもしれません。

...
return (
      <View style={styles.fill}>
        <StatusBar
          backgroundColor="#689F38FF"
          barStyle="light-content"
        />
        <ScrollView
          style={[styles.fill]}
          scrollEventThrottle={16}
          onScroll={Animated.event([
            {
              nativeEvent: { contentOffset: { y: this.state.animateHeader } },
            },
          ])}
        >
          <View style={[styles.scrollViewContent, { minHeight: height - Header.HEIGHT - StatusBar.currentHeight }]}>
            <Markdown>
              {topic.body}
            </Markdown>
          </View>
        </ScrollView>
        <Animated.View style={[styles.header, { height: headerHeight }]}>
          <Animated.Text style={[styles.title, { opacity: opacityContent }]}>
            {topic.title}
          </Animated.Text>
          <View style={{ flexDirection: 'row', alignItems: 'flex-end', padding: 8 }}>
            <Animated.Image
              style={[styles.profileImage, {
                opacity: opacityContent,
              }]}
              source={{ uri: topic.user.profile_image_url }}
            />
            <Animated.Text style={[styles.userName, { opacity: opacityContent }]}>
              {topic.user.id}
            </Animated.Text>
          </View>
        </Animated.View>
      </View >
);
...

まとめ

自分なりのFlutterとReactNativeのメリット・デメリットをまとめます

Flutter

メリット
  • マテリアルデザインを意識せず使える!
  • Viewの書き方が階層的でわかりやすい!
  • Javaライクでわかりやすい!
  • Dartのアプデでより見やすい、書きやすいコードに!
デメリット
  • Stateful?Stateless?なにそれおいしいの?
  • ちゃんとしたアーキテクチャでつくりたいかもしれない

ReactNative

メリット
  • React.jsの知識がそのまんま使える!
  • XMLライクにViewを書ける!
  • Reduxは分かってしまえば最強
  • ライブラリ(パッケージ)が豊富
  • アプデが盛ん
デメリット
  • Reduxを理解するまでに地味に時間がかかる
    • たたみかけるように副作用を扱うためのライブラリの仕様も知る必要がある
  • Viewが複雑になると途端に見にくくなる(Animationを盛り込むとすごい)

クロスプラットフォーム全体としての感想は、どちらもまだアプリとして安定したパフォーマンスを出せていないことですね。あと一生これがサポートされるのか?という不安もあります。
完全なアプリとして採用するのではなく、プロトタイプとしてさらっと作れることが最大のメリットだと感じました。

他にも色々あると思いますが、ざっくりにはこれぐらいだと思います。

以上、ぐだぐだとそれぞれのアプリを作成した内容を書きましたが、これだけ書いてすぐ思ったのが「ただただ長くてわかりにくいな...」ということでした♨️

資料は作ったらここにあげるかもしれないです。おしまい

スカラシップスポンサーとしてDroidKaigi 2018へ行ってまいりました

はじめまして。@nnsnicoです。 2月8〜2月9日にかけて行われました「DroidKaigi 2018」へ参加したレポートとその経緯についてお話していきたいと思います

経緯

今回のDroidKaigi 2018では、学生のためのオトクなプランが提供されていることを公式ページより知りました。それが、タイトルにも書きました「スカラシップスポンサー」というものでした。 何がオトクかというと...

  • 旅費:5万円を上限に補助
  • チケット:100%の割引

ほぼタダ。去年からお金を理由にDroidKaigiに参加することを断念してた僕としては何よりも嬉しいプランでした😄

申し込みは、アンケートとインタビューとのことなのでこれらをやった結果...嬉し恥ずかしながらスカラシップスポンサーとしての参加を認めてもらえました。感無量です。

これでようやく1年に渡って行きたかったDroidKaigiへの参加をすることができました。

参加レポート

今回のDroidKaigiはアーキテクチャに関するお話が割と多い気がしました。僕自身、アーキテクチャにとても興味を持っているマンでしたので、とても勉強になるセクションばかりで嬉しかったです。
2日にかけて行われましたDroidKaigi 2018のセクションの中でも僕が特に大きく知見を得れたと感じられたセクションを感想と共に紹介したいと思います。

How to improve your MVP architecture and tests@kiriminさん

speakerdeck.com

@kiriminさんのMVPアーキテクチャに関するお話です。
MVPによる開発は一度したことのある開発でしたが、MVVMが盛んなこの時期にMVPをフルに活用して開発したお話を聞けたのは大変貴重でした。


AndroidにおけるModel-View-Intentアーキテクチャ@Benoit Quenaudonさん

speakerdeck.com

@Benoit QuenaudonさんのMVIアーキテクチャのお話です。
MVIアーキテクチャというものを初めて聞くもので、かつ事前学習をしていなかったので理解できるものかと思っていましたが、単一方向データフロー型のアーキテクチャだと分かってなんとなく理解できました。イベントが割り込んでもちゃんとデータを保持できるのがすごいですね。一度自分でこれを使ってアプリを実装してみたいですね。(スライドが美しくて途中魅入っていました)


Kotlin版CleanArchitectureのテンプレート作ったら爆速開発になった話+α@Keisuke Kiuchiさん

speakerdeck.com

@Keisuke KiuchiさんのKotlinをCAで実装するためのテンプレを作ったお話です。
CAそのものはiOSアプリの開発のために取り入れていたアーキテクチャでしたが、レイヤ分けやクラスの量がとても多くて基盤を作るのが大変に感じました。 このテンプレートで作成することで、基盤のレイヤとクラスを作成されたプロジェクトが作成されるので、実装が爆速になりそうです!


All you need is isolating the domain(How to apply DDD to Android Application Development 2)@yanzmさん

y-anz-m.blogspot.jp

@yanzmさんのDDDをAndroidに盛り込んだお話です。
前回のDroidKaigi 2017のお話の続きです。DDDは設計思想であり、これをどのようにアーキテクチャとして実装するのか難しい部分がありました。 今回はその部分を特に理解することができる機会になったのでよかったです。
エリックエヴァンス本はやく読破しなければ...


コードで見るFlutterアプリの実装@konifarさん

speakerdeck.com

@konifarさんのDroidKaigi 2018アプリをFlutterで実装したお話です。
最近はReact Nativeを触っていることもあってクロスプラットフォームアプリを開発するためのフレームワークを触ることが少し趣味になりつつあるこの頃。konifarさんがFlutterでDroidKaigiのアプリを開発してくれたお話を聞くことでFlutterの良さを深めることができました。
Flutterの開発言語であるDartJavaっぽいJavaScriptと聞いていたので分かりやすいのでは...!と思っていましたが、Flutterと組み合わせると意外とクセのある言語だなと感じました。(だがそれがいい)


以上、5つしかあげませんでしたが、全てのセクション素晴らしいと思いましたし、本会場で見たかったものも多くありました。

最後に

以上がDroidKaigi 2018の参加レポートでした。僕が得られた知見をまとめました

今回スカラシップスポンサーとして参加をさせてくださいました協賛企業様であるWantedly様、僕に知見をくださいました全ての登壇者様、DroidKaigi 2018を支えてくれたスタッフのみなさま、そしてなにより今回もDroidKaigi 2018を開催させてくださった代表のmhidaka様、本当にありがとうございました。

最近はAndroid触れていないし、Kotlinもにわかなので頑張って追いつかなくては....😅