will and way

ただの自分用メモを人に伝える形式で書くことでわかりやすくまとめてるはずのブログ

InputMethodService(キーボード)開発の勘所となりそうな項目

この記事はAndroid Advent Calendar 2016 - Qiitaの11日目の記事です。

昨日は@yuyakaidoさんのData Binding Tipsでした。 明日は@rei-mさんのDagger2とMockitoでUIテストはじめる話です。

11日目はAndroid StudioでKotlinのプロジェクトが新規で作られるソースを
そろそろKotlinを選べるになってほしいmatsuokahが担当いたします。

InputMethodServiceに触れていて、キーボードのクセを掴まねば!ということで、勘所となりそうな項目を書いてみます。

InputMethodService(以下、ほぼ同義のIME)とは

いわゆるキーボードの継承元となるServiceです。
Simeji、Google日本語入力POBoxATOKが日本では有名ですね。

IMEはググっても、ヒット数が少ないのでマイナーな分野ですね。

IMEアプリの作り方はハンズオン記事を見ればわかります。
サンプルもあります。

ざっくりキーボードの作り方

  1. InputMethodServiceを継承したクラスを作成
  2. Android Manifestにサービスの定義を行う
  3. カスタムしていく

本当にざっくりですがこんな感じです。
ハンズオン記事ではMainActivityに<category android:name="android.intent.category.LAUNCHER"/>を記載していないですが、
設定アプリとしてActivityを使うはずなので消さなくて良いでしょう。

何のメソッドをオーバーライドすべきか?

を見て、リストしてみました。

Intentionally emptyとコメントが書かれているメソッド

  • onBindInput
  • onUnbindInput
  • onInitializeInterface
  • onStartInput・・・初期化
  • onStartInputView
  • onStartCandidatesView
  • onWindowShown
  • onWindowHidden
  • onDisplayCompletions
  • onViewClicked
  • onUpdateCursor
  • onUpdateCursorAnchorInfo

デフォルトでnullを返却しているメソッド

  • onCreateInputView・・・ここでビューを作成する
  • onCreateCandidatesView

デフォルトでfalseを返却している

  • onTrackballEvent
  • onGenericMotionEvent

フルスクリーンモード

  • onEvaluateFullscreenMode・・・画面を回転させた時に、フルスクリーンモードにするか否か

ということで、基本的にはここらへんのメソッドをオーバーライドしてIMEをカスタムしていくことになります。
リストにはライフサイクルに関わるメソッドも含まれています。

また、

ライフサイクル

f:id:matsuokah:20161211020251p:plain

Android Developers - creating-input-methodより転載

というような単純なライフサイクルとなっています。
しかし、思わぬ所でイベントが発火されるケースが幾つかあります。

操作して、ライフサイクルでログを追っていきましょう。

f:id:matsuokah:20161211021719g:plain

これが最もシンプルなIMEの操作だと思います。実際のログは以下のとおりです

## MyImeへ切り替えを開始
D/ImeService: onCreate
D/ImeService: onCreateInputMethodInterface
D/ImeService: onCreateInputMethodSessionInterface
D/ImeService: onInitializeInterface
D/ImeService: onBindInput
D/ImeService: onStartInput, restarting : false
D/ImeService: onCreateInputView
D/ImeService: onCreateCandidatesView
D/ImeService: onStartInputView, restarting : false
D/ImeService: onWindowShown
## IMEの表示が完了

## 別のIMEへの切り替えを開始
D/ImeService: onFinishInputView, finishingInput :   true
D/ImeService: onFinishInput
D/ImeService: onStartInput, restarting : false
D/ImeService: onStartInputView, restarting : false
D/ImeService: onUnbindInput
D/ImeService: onFinishInputView, finishingInput :   true
D/ImeService: onFinishInput
D/ImeService: onDestroy

思わぬ所でイベントが発火されるケース

と、述べましたが onStartInput, onStartInputViewが何故かonFinishXXXの後に呼ばれています。
私はStartと書いてあるのでIMEが立ち上がって入力が開始された時だけ発火すると勘違いしていました。

ではなぜ発火されているか。それは、編集していたEditTextのフォーカスが外れた時に、IMEの状態をリフレッシュするためです。

IMEは1つのインスタンスであるのに対し、画面には複数のEditTextが存在することが多いです。
編集するEditTextが切り替わると、すでに入力されているテキストや入力タイプ(Numeric, AlphaNumeric, Passwordなど)が変わります。
したがって、onStartInputでは一時的な入力データなどを破棄し、引数で与えられているEditorInfoオブジェクトの情報から次の入力に備える必要があります

実はSDKのドキュメント冒頭にあるGenerating Textという項目で述べられています。ドキュメントはしっかり読もう。

そして、ログに出てきてないので気づきにくいのですがonWindowShownに対し、onWindowHiddenが呼ばれていません。
onWindowHiddenIMEが破棄されないが非表示になるときタスクマネージャ起動時に発火されます。

従ってonWindowHiddenでTearDownするのは好ましくない実装だと思います。

onStart系のライフサイクルメソッドでスクラップアンドビルドしていくのが良いかなと個人的に思います。

Fragmentが使えない

私はIMEでもFragmentが使えると思いこんでいました。
ところがFragmentはActivityに依存しているのでServiceで使えないのは当然なわけであります。

iOSのLINEのスタンプのようなUIを実装してみようと思っていたのですが、
Fragmentが使えないのでViewPagerを使うにはAdapterの独自実装が必要となります。

LINEのUIなので、画像が多い前提となるため、Fragmentのライフサイクルの様にページを破棄することも考慮に入れる必要があります。

ということで、ひとまず最低限の実装でFragment・FragmentManager・FragmentPagerAdapterの実装を真似て作ってみました。FragmentのTransactionは実装していません。

f:id:matsuokah:20161211035021g:plain

ImeFragment.kt

abstract class ImeFragment() {
  lateinit var service : InputMethodService
  val context : Context
  get() = service


  var tag : String = ""
  var containerId : Int = 0
  var view : View? = null

  open fun onCreate() {}
  open fun onCreateView(inflater: LayoutInflater, container : ViewGroup?, savedInstanceState : Bundle?) : View? { return null }
  open fun onAttach() {}
  open fun onDetach() {}
  open fun onDestroyView() {}
  open fun onDestroy() {}
}

ImeFragmentManager.kt

class ImeFragmentManager(val service : InputMethodService, val rootView : View) {

  val fragments : HashMap<String, ImeFragment> = HashMap()
  val attached : HashMap<String, ImeFragment> = HashMap()

  fun add(containerId : Int, imeFragment : ImeFragment, tag : String) {
    if (fragments.containsKey(tag)) throw IllegalArgumentException("already container has fragment")

    imeFragment.containerId = containerId
    imeFragment.tag = tag

    fragments[tag] = imeFragment
    attach(containerId, imeFragment, tag)
  }

  fun remove(tag : String) {
    if (attached.containsKey(tag)) {
      detach(attached[tag]!!)
    }

    val fragment = fragments[tag]!!
    fragment.onDestroy()
    fragments.remove(tag)
  }

  fun findFragmentByTag(tag : String) : ImeFragment? = fragments[tag]

  fun attach(containerId : Int, imeFragment : ImeFragment, tag : String) {
    if (!fragments.containsKey(tag)) throw IllegalArgumentException("fragment is not added")
    if (attached.containsKey(tag)) throw IllegalArgumentException("already container had attached")
    attached[tag] = imeFragment

    imeFragment.service = service
    val container = rootView.findViewById(containerId) as? ViewGroup
    imeFragment.view = imeFragment.onCreateView(LayoutInflater.from(container?.context), container, null)

    container?.addView(imeFragment.view)
    imeFragment.onAttach()
  }

  fun detach(imeFragment : ImeFragment) {
    if (!attached.containsValue(imeFragment)) throw IllegalArgumentException("fragment not found")
    val container = rootView.findViewById(imeFragment.containerId) as? ViewGroup
    container?.removeAllViews()
    imeFragment.onDestroyView()

    attached.remove(imeFragment.tag)
    imeFragment.onDetach()
  }
}

ImeFragmentPagerAdapter.kt

abstract class ImeFragmentPagerAdapter(private val imeFragmentManager : ImeFragmentManager) : PagerAdapter() {

  abstract fun getItem(position : Int) : ImeFragment

  override fun instantiateItem(container : ViewGroup?, position : Int) : Any {
    container ?: throw IllegalArgumentException("")

    val tag = createTag(container.id, position)
    var fragment = imeFragmentManager.findFragmentByTag(tag)

    if (fragment == null) {
      fragment = getItem(position)
      imeFragmentManager.add(container.id, fragment, createTag(container.id, position))
    } else {
      imeFragmentManager.attach(container.id, fragment, createTag(container.id, position))
    }

    return fragment
  }

  override fun destroyItem(container : ViewGroup?, position : Int, obj : Any?) {
    val fragment = obj as ImeFragment
    imeFragmentManager.remove(fragment.tag)
  }

  override fun isViewFromObject(view : View?, obj : Any?) : Boolean = (obj as ImeFragment).view == view

  companion object {
    fun createTag(viewId : Int, itemId : Int) : String = "android:ime_switcher:$viewId:$itemId"
  }
}

Fragmentっぽい実装を用意することで、Page単位にコントローラを分離できること・ドメインレイヤーとの繋ぎの所にもできるので欠かせないな〜という所。
ココらへん、ライブラリ化して公開します。多分。

小ネタ. Macで音のボリュームを無段階調節

知らなかったので驚いた

Shift + Option + Functionキーで音量とかディレスプレイ輝度の調整がより細かくできる!!!

普通にボリュームup/downすると以下のようにメモリ毎にボリュームが変わりますが

f:id:matsuokah:20161205223454g:plain

Shift + Optionを推しながら調節すると・・・

f:id:matsuokah:20161205223539g:plain

うおおおおおおおおおおおおおおおおお!!

f:id:matsuokah:20161205223815g:plain

うおおおおおおおおおおおおおおおおおおおおおおおおおおおおおお!!

f:id:matsuokah:20161205223902g:plain

ま、そんなに細かく調整する必要ないんですけどね

僕のPCはMBPですが壁紙はiMacの基盤です

Androidのコードを書く前にコーディングに集中できる状態を作る

はじめに

この投稿はAndroid その3 Advent Calendar 2016 - Qiitaの5日目の記事です。

4日目はkimukouさんのrealm-gradle-plugin 2.2.1 と Android Realm Browserでした。
6日目はkimukouさんの2016年末のAndroidでのSSL対応に関してです。

Androidのコードを書く前にコーディングに集中できる状態を作る

今年のAdvent CalendarはAndroidでKotlinを導入する話がかなり多くて、Kotlinが浸透しているんだな〜と感じています。
かくいう私もKotlinを使ってみた所感やテクニックのネタを考えてたんですが、Kotlinは愚かAndroidを本格的に開発し始めて2ヶ月ですので、エキスパートな部分は先人達にお願いするとします。

最近異動して、0からのプロジェクトに携わらせてもらっていて、コードを書く前に環境を整えることを最初にやりました。その時のまとめになります。

目次

  • なぜやるべきか。ずばり何をするのか
  • 命名規則, Code Style
  • プロジェクト構成, BuildType/Product Flavor, DI
  • データ層からプレゼンテーション層のサンプル実装
  • CI
  • プルリクのルールを作る
  • 必ず使うSDK, ツールの導入
  • テンプレートコード・スニペットをつくる
  • 開発環境のプロビジョニングをつくる

なぜやるべきか。ずばり何をするのか

プロジェクト初期になぜやるべきか。
先に決めて開発期〜リリースの間にコーディングに集中できる環境があると、エンジニアの精神衛生が良い状態が保たれるからです。 そして、プロジェクトが発足したての頃は仕様が 無い or 部分的 or 一朝一夕で変わるが当然なので機能実装以外に時間を割く時間が作りやすいです。

ずばり何をするのか。
ルール化自動化です。
プルリクを前提とした開発では、コードレビューのコストを大幅にされるでしょう。ルールと自動化をメンテしましょう。コードレビューで主観的(書き方の好み)な議論をするのは楽しいですが開発スピードとのトレードオフになります。世に出ていないサービスはスピードの方が重要でしょう。

では、さっそく各項目について、まとめをつらつらと書いていきます。

命名規則, Code Style

命名規則

大雑把なルールを作り、必要になったらルールを追加していきます。

接頭辞 or 接尾辞

リソースは接頭辞ベース、クラスは接尾辞ベース
Android Best Practices#Resourcesをベースにすると良い。日本語にも翻訳されています。

レイアウトの変数に名前をつける

レイアウトの変数名に概念や機能性をもたせることで、デザイナーと列挙された数値の共通認識をもつことが出来ます。 Androidはldpi(x0.75)を考慮して4の倍数でレイアウトをする必要があるので、そこだけ3dpみたいなことは極力避けたいです。

現在のプロジェクトではマージンやパディングの数値(4, 8, 16, 24)にspacing_s, spacing_m ... と名前をつけてます。

フォントのサイズにはHTMLのタグ名を参考にすると良いかもしれません。
title, header, body, paragraph ...
コンテンツの優先順位でフォントサイズを変えるということが直感的になります。

※ルール化することでデザイナーの発想の範囲を狭めることがあります。

Code Styleをととのえる

スペースや改行は好みが分かれるので、先にルールを決めるのがいいです。
Code StyleはAndroid界隈の神らしい、Jakeが在籍するSquareのコードフォーマットを拝借しましょう。

フォークして微調整してプロジェクトのルールとするのが手っ取り早いです。Google Java Style Guideをベースにチューニングします

プロジェクト構成, BuildType/BuildVariants, DI

プロジェクト構成をつくる

いわゆるアーキテクチャです。MVP/MVVM/MVCなどのパターンから、どれで実装していくかを決める必要があります。

BuildType/Product Flavorを追加する

ビルドタイプを分ける(Debug, Release)
  • ロギングの切り替え(コンソールログ/クラッシュログをサーバーに転送する)など
環境を分ける(development, staging, production)
  • Endpointの切り替え
  • アプリアイコンなどのリソースを環境毎に変える
  • KeyStoreの切り替えをtaskに含める

DIを導入する

上記のアーキテクチャとビルドタイプを統合した構成を考える必要があります。 勘所はAPIのエンドポイントやログ、モックデータを返却するAPIなどを切り替えられるように意識しましょう。

例えば、Retrofitを使っているプロジェクトでdebug/release毎にRetrofitのインタセプタのDIの戦略を変えるというような事です。 debug時だけloggerのインタセプタのDIを有効にしてAPIアクセス時のに詳細なロギングをするといったことが可能です。

現プロジェクトではDIにDagger2を使っており、インスタンス戦略は

  • Context(Application)スコープ
  • View(Activity/Fragment)スコープ

の2つに着地しています。Contextレベルなのはドメインレイヤーから下です。

データ層からプレゼンテーション層までの一気通貫サンプルを実装する

プロジェクト構成が出来たら、その構成が本当に使いやすいか検証する必要があります。自分で実装してみるのが一番です

サンプル実装でマニュアルも同時に終わらせることが出来ますし。そして、Android初心者な私にとって一気通貫させるのは実装イメージを沸きたてるにはベストでした。

CIを導入する

とりあえずFastlaneを導入してFastfileで各環境のビルドをできるようにしておくことが重要。

Gemfileも定義して、bundle exec fastlane [ENV] type:Debugくらいのコマンドでビルドできるようにしておけば、Circle CIを導入してもdeploymentディレクティブでの細かな設定が不要になります。

実際に運用しているのは

  1. Circle CIでbundlerをつかってfastlaneをフック
  2. ターゲットとなる環境のアプリをビルド
  3. Crashlytics Betaにアプリをポストし、テスターグループにアプリを公開
  4. Slackにビルド完了通知

Fastfileにはフローを定義し、Contextにプロジェクト情報を埋め込む形に着地しています。

※FastfileはBuildType, BuildVariants, Keystoreの設定と合わせる必要があります。

プルリクエストルールを作る

前のプロジェクトのチームのプルリクにはルールが定められていて、1年以上つづけていて、とてもよかったたので概要を紹介。

  1. プルリクのフォーマット化
    1. 概要、バグフィクスの原因など
    2. 目的やアクションを記載する(仕様を含む、編集の意図をソースコードから汲み取らない)
    3. 修正の影響範囲がわかるURLを含める(開発ロードマップやCSのバグチケ)
  2. UI変更はBefore/Afterのスクショ必須
  3. インタラクションならGIFアニメ必須

詳細は割愛します。Cookpadさんの開発速度を上げるための Pull-Request のつくり方に近いです。

必ず使うSDK, ツールの導入やリスト作成する

仕様にかかわらず必要となる機能やツールは少なくとも決まってるので時間があるときに導入だけしておくことで、終盤で導入して急遽Multi Dex対応が必要になるみたいな事が減らせると思います。

テンプレートコード・スニペットをつくる

Dagger2を使う場合にはComponent, Module, Scopeを大量生産するでしょう。
IntelliJにはファイルテンプレート機能があり、予めApache Velocityのフォーマットに従った形式でソースコードを書いておけば、ファイルの新規作成時に選ぶことが出来ます。 テンプレート化によって、フレームワークを使うときのフットワークを軽くすることが出来ます。

#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}

#end
#parse("File Header.java")

import javax.inject.Scope
import kotlin.annotation.AnnotationRetention.RUNTIME

@Scope
@Retention(RetentionPolicy.RUNTIME)
annotation class ${NAME}

開発環境のプロビジョニングをつくる

AnsibleでAndroid SDKのインストールを図る。

Android Studioがよしなにやってくれることも多いので、ツール群の導入くらい。

まとめ

プロジェクトを始める発射台となるような手順をまとめた。とにかく最初は開発しやすいように、大雑把なルールや開発を加速させる周辺を整える事が重要。

そして、ユニットテストやUIテストの導入がまだできてないので、これからやりたい。

あわせて読みたい

blog.matsuokah.jp

Android 2.3系, 3.0系を対応しているならそろそろ潮時なのかもしれない

Highlights from the Google Play services 10.0 release.

Google Play Servicesのv10系がリリースされ、リリース文の序文に

Google Play services 10.0.x is the final release that includes full support for Android version 2.3.x

2.3を切るよと書かれている。

android-developers.blogspot.jp

The next scheduled release of these libraries, version 10.2.0, will increase the minimum supported API level from 9 to 14 (Android 4.0.1, Ice Cream Sandwich).

次のリリース予定である10.2.0ではminSdkをv14(Android 4.0.1)に引き上げる予定とのこと。

更にAndroid Developersブログの案内では続けて v10.0.0系をlegacy, v10.2.0系をcurrentというProduct Flavorsを作成し、Multiple APKを使えばいいと案内しているが

メンテコストが膨らむのが目に見えてるでしょ。

10.0.0系と10.2.0系以降のライブラリのインターフェースや動きが同じとは限らない。

切り時なのだね。きっと。

Androidの開発にはIntelliJでも良いじゃんと気づいた話

f:id:matsuokah:20161204181038p:plain

IntelliJをインストールしていながらもAndroid Studioを使っていたが IntelliJAndroidプロジェクトを読み込んでみたら、Android Studioと全く同じように開発できた。

そして、上位互換だった。そんな話。

社会人になってからの職歴とエディタ歴は

ざっくりこんな感じ。

IntelliJに1年だけデビューしておき、その後は惰性でアップデートしていたので損してたな〜。

Android StudioIntelliJの若干古いバージョンがベースとなって無料配布されているだけ

Android Studio2.2はIntelliJ IDEA 2016.2がベースとなっている。

IntelliJ最新バージョンは 2016.3である。

Constraints Layoutは2016.2ベースのAndroid2.2に含まれているのに対し、2016.3の機能となっている。

メリット/デメリット

メリット: Kotlinの最新の機能がいち早く使える

ちょっとしたメリット. どっちも持ってるならIntelliJを使うという選択をすべき。

What's New in IntelliJ IDEA - 2021.3

上記の2016.3 whats newにも記載されていますがKotlinのPostfix Completionが先行して使えるようになっている。

Postfix Completionというのは以下のGIFのようなコード補完機能です

f:id:matsuokah:20161204171400g:plain

いわゆるLiveTemplateをその変数にスコープを絞った機能といった所。

以下のGIFはLiveTemplateで同じコードを書いた場合。変数を絞り込んでいく手間を感じる。

f:id:matsuokah:20161204171834g:plain

ちなみに、Android Studio 2.2ではまだ使えない

blog.jetbrains.com

上記の記事によると

Note that the feature depends on platform changes made in IntelliJ IDEA 2016.2 and is therefore unavailable in Android Studio 2.2;

ということで、Android Studio 2.2ではこの恩恵を授かれない。LiveTemplateは使える。

もちろん、IDEとしての機能はIntelliJを使ったほうが先に使えるので、そのアドバンテージはあると思います。

デメリット: IntelliJのほうがAndroidの最新機能を使えるようになるのが遅いかも

Android Studi 2.2 Release
-> 2016/09/19 Release!

IntelliJ IDEA 2016.3 GA: Java 8 and ES6, Debugger and UI improvements, and a Ton More
-> 2016/11/22 Release

  1. IntelliJ 新機能(Android Studioのベースとなるバージョン)
  2. Android Studio(ここでAndroidの機能が追加)
  3. IntelliJ(IntelliJAndroid Studioと同等の機能が追加される)

というアップデート順だとしたら、Androidの新機能が使えるようになるのは若干遅いかも?

Android Studioで試験的に導入してから、IntelliJに導入してるのだろうか。

Android StudioからIntelliJへの移行をするには?

Android SDKを設定する

  1. Android Studioの設定からAndroid SDKのパスを設定する

  2. Confiture > Project Defaults > Project Structure f:id:matsuokah:20161204172242p:plain

  3. SDK > + > Android SDK f:id:matsuokah:20161204172331p:plain

これでAndroidプロジェクトが作成・ビルド可能になります。

f:id:matsuokah:20161204173032p:plain

見慣れた編集画面。

Kaptを使っている場合はgenerateStubsを有効化する

kapt {
    generateStubs true
}

上記の設定を入れるだけで筆者の環境ではビルドできた。

before : 17sec after : 20sec

コンパイル時間が若干、長くなる。

参考:
qiita.com

IntelliJユーザーとAndroid Studioユーザーが共存できるのか?

できます。 Code Styleの設定ファイルなんかも、形式が同じなのでAndroid Studioの設定をExportしてIntelliJに読み込むとも可能

メルカリでロードバイクを売った話と防犯登録の手続きでハマった話※追記あり

全然、最近乗ってなかったので持ち腐れと思いメルカリで売ってみた。その時の話。

自転車を譲渡するって意外と大変だなーって思った事が意外とあった。
特に自転車の場合は防犯登録があるが、手続きの順序をしらないと手間が増えるのでメモ書き程度に残してみた。

TR;DR

1. メルカリで売ってみる

実は使ったことがなかったので、売るシステムがどんなものか知りたくて使ってみた。

写真を投稿する

写真は約4枚。ロードバイクの全体像、おまけ、そして保証書(シリアルナンバー)の写真を投稿した。

価格の設定

強気に設定してたら何度か値段交渉をされましたが、どれもYahooオークションでの相場を遥かに下回る価格だった。
そういうもんかと思ってたら、メルカリの通知で「このくらい下げてみましょう」というサジェストが来た。

実際下げてみると、だいたい妥当な交渉額が提示されたのでそれで手を打つこととした。

合計30万くらいかかったロードバイク・アクセサリが14万円で売れた。
ロードバイクは型落ち品の値落ちが激しい部類のようで、他のバイクもだいたいそんなもんだった。

交渉ははっきり断る

個別で販売するのが面倒で、アクセサリをおまけとして売っていたら、別売のコメントがいくつもついた。
全部断った。何度も運送会社とやり取りするのがだるい。

2. ロードバイクを送る

他のロードバイク販売者の輸送方法をみてたらカンガルー自転車輸送便が紹介されていた。
最初はヤマトなどを使おうと思っていたが、他の運送会社では自転車を扱う場合には大きい荷物として送るので、輸送費が非常に高くなってしまうようだった。

カンガルー自転車便はレンタル箱代と輸送費で1万円以内に収まるので割安で送ることができる。

  1. 輸送申請(料金前払い)
  2. 輪行箱が届く
  3. 集荷
  4. 配達

という流れになっていて、輸送申請から集荷までは約1週間かかった。輪行箱が届く日は申請日から3, 4日以降でないといけないらしく気長な感じ。

箱が届く

f:id:matsuokah:20161127161612j:plain

フタはこんな感じ

f:id:matsuokah:20161127161613j:plain

フタには説明書が貼り付けてある

f:id:matsuokah:20161127161614j:plain

箱の横面には高価品などの扱いが書かれている。

f:id:matsuokah:20161127161618j:plain

前輪を外していれる

f:id:matsuokah:20161127161619j:plain

フロントフォークに傷がつかないようにプチプチで包んで送りました。

すっぽり入る

f:id:matsuokah:20161127161621j:plain

ハンドルを曲げて入れる必要があったのと、ペダルを外す必要があった。
ペダルレンチを持ってなかったので、近くの自転車ショップに持っていって外してもらった。

ペダルもプチプチに。

受取の評価を待つ

メルカリでは受取人の評価と販売人の評価をして初めてお金が入るシステム。 それによってトラブルが起きないようになっているようだった

簡単に出品できたのと手数料がヤフオク(落札額の10%)に比べて格安だったのでなかなかよかった。

防犯登録の抹消と再登録

抹消は本人がするか、譲渡先に書類を渡すことで再登録の手続きと同時に行うことができる。

正しくは

抹消は本人がするか、譲渡先に書類を渡すことで再登録の手続きと同時に行うことができるのは同じ都道府県内の譲渡のみ。譲渡先と都道府県が一致しない場合は管轄が変わるため、先に抹消手続きを完了してからでなければ、他県で手続きすることができない。

神奈川県の自転車防犯協会に問い合わせた所、上記のような回答がもらえた

必要な書類とは

  • 防犯登録のときにもらった防犯登録のお客様控え
  • 譲渡証明書

のどちらか。

神奈川県の自転車防犯協会によると、

譲渡証明書の書式は定めておりません。サンプルがありますのでダウンロードしてご使用ください

と、サンプルが載っている。これは自治体ごとに必要書類が変わるかもしれないので、譲渡元と譲渡先の防犯登録の管理団体に問い合わせるのがベスト

marble diagram

marble diagramとは

Reactiveプログラミングの説明に使われるあの図の名前。

f:id:matsuokah:20161109005612p:plain

RxMables#mapより転載

X軸を時間、Y軸をストリームとしていて、4つの登場人物は以下の通り

○: input data event
X: error event
|: complete event
中間の□: transformer

つまり、

データ入力イベントが発火→transformerでデータの変換→出力という一連の流れを表している。

何のために使われている?

Reactive Programmingは数多くのオペレータ(transformer)があります。その役割の説明のために使われている。

ジムに行き始めて4ヶ月が経った

健康診断で2年連続

  • LDLが高い
  • 血中脂肪が高め
  • 貧血

と言われ、男性の貧血は稀ということで精密検査まで受けたにも関わらず原因不明。この5年間風邪もひかず、全くもって健康体だと思ってたのに悔しい。

一念発起して体質改善をすべくジムに行き始めて早4ヶ月。なかなか健康体になってきたと思うので、まとめてみた。

f:id:matsuokah:20161022191353p:plain 毎週2,3回は行っていて、帰宅が遅くなったときは家でやってるので週3は筋トレする時間を確保している。

f:id:matsuokah:20161022191632p:plain

f:id:matsuokah:20161022191635p:plain

f:id:matsuokah:20161022192222p:plain

体脂肪率は11%前後、身長174cmに対し、標準体重65.8kgまでもう少し!

ジムに行き始めて変わったこと

  • 体が軽くなったとかは感じないw
  • 食生活を気にするようになった

体調のブレは少なくなったように感じる。筋力が上がったからではなく、生活習慣が変わったから。
ゲームで夜更かしすることが多かったが、程々で寝るようになった。結論、自分の体は睡眠が重要みたい。

食生活を意識する

  • フレッシュフルーツ、ドライフルーツ、ナッツ類を多く食べる
  • 定期的にプロテインを飲む
  • 常温かそれより温かい水を飲む
  • グルテンを避ける(GI値の低い物をなるべく選ぶ)
  • スナック類、カップラーメンは食べない

グルテンフリーはジョコビッチの本で知った。アレルギーではないけれど、積極的には食べないようにしている。
付き合いや出してもらったものは喜んで食べてる。ラーメンは4ヶ月位食べてない。

プロテイン事情

最初はSAVASなどのプロテインを飲んでいたが甘いのが好きではないので、最近は甘味料が入っていない無添加のプロテインを飲んでいる。 無添加なのでホエイ以外入っていない。ビタミン類も取りたいので、無糖の青汁を混ぜて飲んでいる。

プロテインだけ→低脂肪牛乳みたいな味
青汁→青臭い

プロテイン + 青汁 → 抹茶オレ

普通に美味しい。もともと、プロテインのみで飲んでたが、この記事を書く1週間くらい前に発見して、かなり感動した。

成分表

f:id:matsuokah:20161022195821j:plain
プロテイン

f:id:matsuokah:20161022195846j:plain
青汁

自宅の筋トレ

家には重さ調節が1kg~10kgでできるダンベル2個フィットネスマットだけ置いている。
フィットネスマットはなくても良いんだけど、汗を床につけたくないし、下の階の人に迷惑かけたくないという理由も兼ねて。

家で体幹トレーニングしながら動画を見るのは相性がいい。
たまった録画の消費、Youtube見ながらプランクやらV字バランスしてる

長友の本は良かった。けど、naverまとめでやり方は見つかる

来る健康診断

去年は会社の健康診断が10月〜11月頃に行われた。今年の健康診断では超健康体な結果を叩き出すんだ!!