My Note Pad

エンジニアリングや日々の雑感を書いていきます

【Android学習】FragmentをKotlinでやってみる

今更感がありますが先日、Udemyを眺めていたところ、以下のコースが目に留まったので、Android開発の学習を進めています。 ※セクション3:Java Deep Diveなど、自分には必用なさそうな部分は省いています。

www.udemy.com

レッスン自体はAndroid N向けの内容のため、最新のAndroid Studioなどではlayoutを作るときに若干勝手が違って苦労する部分もありますが、コース自体はよくできているなという印象です。

しかし、Fragmentを使いたくなったのですがコース内を選択してもヒットしなかったので、こちらの記事を参考に試してみました。

qiita.com

また、Javaでそのまま写経するのもな・・という感じだったので、Kotlinで書いてみました。

レイアウトファイルの作成

まずはFragmentを作成します。
HogeFragmentとかだと味気ないのでにQiitaの例にmakerbrandという項目を追加して、CarDetailFragmentという名前にしてみました。

Fragment作成はapp -> New -> Fragment -> Fragment(Blank)で空のFragmentを作成しました。

レイアウト fragment_car_detail.xml はこんな感じになります。 f:id:yuki10k:20180429213647p:plain f:id:yuki10k:20180429213654p:plain

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".CarDetailFragment">

    <!-- TODO: Update blank fragment layout -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:id="@+id/helloText"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:text="Hello Fragment"
            android:textAlignment="center"
            android:textSize="24sp" />
        <Button
            android:id="@+id/numberButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="1" />
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <TextView
                android:id="@+id/makerText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="maker" />
            <TextView
                android:id="@+id/brandText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="brand" />
        </LinearLayout>
    </LinearLayout>
</FrameLayout>

Fragmentのコード作成

CarDetailFragment.ktになります。
デフォルトでいろいろメソッドが宣言されているのですが、一旦消して書き直しています。

Kotlinならではのイディオムがあったりしますが、難しいことはないと思います。
断片的に書いていって、最後に全体を書きます。

まずは変数宣言です。
lateinitで後で初期化するよと明示しています。

    private lateinit var mTextView: TextView
    private lateinit var maker: String
    private lateinit var brand: String

続いてcompanion object。
定数やJavaでいうところのstaticメソッドはここに定義しました。
createInstanceメソッドでは、インスタンス生成時にパラメーターを受け取って、Bundleに渡してFragmentのargumentsにセットしています。

    companion object {
        private const val KEY_MAKER = "maker_name"
        private const val KEY_BRAND = "brand_name"

        fun createInstance(maker:String, brand:String): CarDetailFragment {
            val carDetailFragment = CarDetailFragment()
            val args = Bundle()
            args.putString(KEY_MAKER, maker)
            args.putString(KEY_BRAND, brand)
            carDetailFragment.arguments = args
            return carDetailFragment
        }
    }

あとはFragmentのライフサイクルメソッドを実装していきます。
ライフサイクルは公式の図がわかりやすいと思います。

developer.android.com

今回は、

  • onCreate ・・・ パラメータを受け取ってメンバ変数にセット
  • onCreateView ・・・ Viewの生成
  • onViewCreated ・・・ View生成後の操作

を実装しています。
全体は↓こんな感じになりました。

// packageは省略

import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView

class CarDetailFragment : Fragment() {

    private lateinit var mTextView: TextView
    private lateinit var maker: String
    private lateinit var brand: String

    companion object {
        private const val KEY_MAKER = "maker_name"
        private const val KEY_BRAND = "brand_name"

        fun createInstance(maker:String, brand:String): CarDetailFragment {
            val carDetailFragment = CarDetailFragment()
            val args = Bundle()
            args.putString(KEY_MAKER, maker)
            args.putString(KEY_BRAND, brand)
            carDetailFragment.arguments = args
            return carDetailFragment
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val args = arguments
        if (args == null) {
            maker = ""
            brand = ""
        } else {
            maker = args.getString(KEY_MAKER)
            brand = args.getString(KEY_BRAND)
        }
    }

    override fun onCreateView(inflater: LayoutInflater,
                              container: ViewGroup?, savedInstanceState: Bundle?): View? {
        super.onCreateView(inflater, container, savedInstanceState)
        return inflater.inflate(R.layout.fragment_car_detail, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        mTextView = view.findViewById(R.id.helloText)
        view.findViewById<Button>(R.id.numberButton).setOnClickListener {
            mTextView.text = "${mTextView.text}!"
        }

        val makerText = view.findViewById<TextView>(R.id.makerText)
        makerText.text = maker

        val brandView = view.findViewById<TextView>(R.id.brandText)
        brandView.text = brand
    }
}

Fragmentを呼び出すActivityの作成

こちらもFragmentと同じように app -> New -> Activity -> Blank Activityで作成します。

LinearLayoutだけ定義し、中身は空っぽにしておきます。

f:id:yuki10k:20180429221650p:plain

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".CarDetailActivity">

    <LinearLayout
        android:id="@+id/carDetailContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"></LinearLayout>
</android.support.constraint.ConstraintLayout>

CarDetailActivity.ktは以下のような感じになりました。
パラメーターとして

という文字をFragmentに対して渡しています。

// packageは省略

import android.support.v7.app.AppCompatActivity
import android.os.Bundle

class CarDetailActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_car_detail)

        // コードからフラグメントを追加
        if (savedInstanceState == null) {
            val transaction = supportFragmentManager.beginTransaction()
            transaction.add(R.id.carDetailContainer, CarDetailFragment.createInstance("TOYOTA", "プリウス"))
            transaction.commit()
        }
    }
}

実際に実行して、CarDetailActivityを開くと、以下のようにFragmentの内容が表示され、パラメータの受け渡しが行われていることが確認できました。

f:id:yuki10k:20180429222155p:plain

最初はなかなかとっつきにくいなーと思っていましたが、実際に触ってコードを書いていくと、「あーなるほど」という感じで少しづつ理解ができてきました。

引き続き時間を見つけて色々実装を試してみたいと思います。

Air Podsを買ったら最高だった

Air Podsを買いました。

www.apple.com

前々から欲しいなとは思っていましたが値段が値段なのでなかなか踏ん切りがつかず、Ear Podsをずっと使っていました。
何度かBluetoothイヤホンを使ったことがある身としては、iPhoneから伸びるEar Podsのケーブルは非常に邪魔で、しょっちゅうイライラしていました。
また、先端がLightningケーブルになっているため、Macには刺せないのも不便だなと感じていました。

そんな中、AppleStoreギフト券を貰ったのでせっかくのチャンスなのでAir Podsの購入に踏み切ることに。 「2018年には進化したAir Podsが出る」といった噂や、「ケースがAir Powerに対応して発売される」といった噂があり正直迷いましたが、Air Power充電は別にいいかなと思い、購入しました。

早速Apple Storeを見ていると、ネット注文では7営業日・・・
しかし、店舗だと在庫があるようで、直接店舗に行って購入することに。

無事にゲット。
アクセサリでもAppleの商品を開封するときのワクワク感はたまりません。

蓋を開けると恒例の「Designed by Apple in California」

さらに奥に進むと、Air Podsケースを発見

その下にはLightningケーブルが入っていました。

ついにケースとご対面。

早速ケースを開けると・・・
iPhoneが反応し、Air Podsとの接続確認ダイアログが出現。
接続ボタンを押すとすぐにiPhoneAir Podsの接続が完了しました。
このユーザー体験はAppleならではと関心します。

最後に本体をケースから取り出してみました。
若干マグネットになっており、蓋を空けてもケースから落としにくい親切設計。

同じApple IDの端末にはシームレスに切り替わるはずですが、複数のデバイスが近くにある場合には、iPhoneMacからAirPodsに接続してあげる必要がありました。

iPhoneの場合、「コントロールパネル?」からミュージックパネルの右上のアイコンを選択すると

音を出すデバイスが選べるので、Air Podsを選択するとAid Podsと接続ができます。

また、Bluetoothの接続画面から、Air Podsのダブルタップ時の動作も設定できます。
Siriを割り当てることもできますが、「再生/一時停止」を割り当てておくと、iPhoneに触ること無くAir Podsを耳にセットしてAir Podsをダブルタップすると音楽が再生されるのでかなり便利です。

「耳からうどん」などと言われることもありますが、最近では街中でAir Podsを耳に着けているユーザーもちらほら見かけるようになってきたので、あまり目立つこともなくて良いかも。

まだまだ使い倒せていないですが、これからどんどん使い倒していきたいと思います。

Raspberry Pi Zero W Starter Kitを購入してみた

会社でRaspberry Piを使って何かやってみようということになったので、Raspberry Pi Zero WのStarter Kitを購入してみました。
開封しつつ、リモートデスクトップ接続・SSH接続までできるようになったので書いていきます。

※設定には最低限キーボードがあればいいのですが、マウスもあったほうがいいです。
 その場合USBポートは一つしか無いので、USBポート拡張用のアダプタなどが必用になります。

まず届いたのはこちら。簡易な包装です。
SDカードにはOSインストール済のものが入っているので、一度開封した痕がありました。
f:id:yuki10k:20180119005048j:plain

中身を取り出すとこんな感じ。
本体は結構小さいです。

f:id:yuki10k:20180119005054j:plain

ケースの中には滑り止めとカメラモジュール用のケーブル(?)が入っています。

f:id:yuki10k:20180119005057j:plain

本体にSDカードを差し込みます。
※この画像でいう左側です。 f:id:yuki10k:20180119005107j:plain

そのままケースに装着。
横にUSBの穴などが空いているので、方向を間違えることはなさそうです。 f:id:yuki10k:20180119005100j:plain

横から見るとぴったりとハマっていました。 f:id:yuki10k:20180119005105j:plain

起動するとOSのインストール画面になりました。
Raspbianを選択してそのままインストール。 f:id:yuki10k:20180119005111j:plain

起動し終わったら、以下の2記事を参考に、セットアップとリモートデスクトップ必用なパッケージのインストールをしていきます。

qiita.com

qiita.com

設定と再起動が終わったら、早速リモートデスクトップ接続を試してみます。

手順どおりに行って、ユーザー/パスワードを特に変更していない場合、以下のようになると思います。
※設定が全て終わったら少なくともパスワードは変えた方が良いです。

接続先raspberrypi.local
ユーザー名pi
パスワードraspberry

必用な情報を入力し f:id:yuki10k:20180119005120p:plain

「はい」を選択 f:id:yuki10k:20180119005128p:plain

パスワードを入力して「OK」 f:id:yuki10k:20180119005131p:plain

これでRaspberry Piにデスクトップ接続できました。 f:id:yuki10k:20180119005135p:plain

SSHも試してみます。
今回はRLoginを使いましたが、Macであれば普通にsshコマンドで入れると思います。

必用な情報を入力して、「OK」 f:id:yuki10k:20180119005137p:plain

無事にSSH接続できました。 f:id:yuki10k:20180119005140p:plain

リモートデスクトップではRaspberry Pi Zeroのスペック不足か、もっさりすることはありましたが、
SSH接続であればあまり気にすることなく作業できそうでした。

よいRaspberry Lifeを。

iPhoneXを購入したので開封の儀!

iPhoneX 予約から購入まで

ようやくiPhoneXが発売されました!
発表されてしばらくは、「iPhone7でいいかな・・」と静観するつもりだったのですが、予約開始日が近くなるにつれどんどん興味が湧いてきて予約してしまいました。

予約日は16時前にはiPhoneを構えて待機し、無事11月3日受け取りで予約できました。
今回はiPhoneのAppleStoreアプリで予約しました。
そして本日、アップルストアでピックアップしてきました!

アップルストアに着いた時にはすごい行列が・・・
2時間くらい待つのを覚悟して行列の最後尾のスタッフの方に

「ピックアップってこの行列ですか?」

と聞いたところ、

「店舗入口でスタッフに話しかけてくれたらすぐに受け取れるよ!」

と。
良かった・・

店舗前で再度スタッフに話しかけ、ピックアップの旨を伝えると、
QRコードを見せてすぐに入店できました。
支払いは済んでいるので、身分証明書を見せてサインしてあっさり受け取り完了。

今回購入したのはiPhone X スペースグレイの64GBです。

いよいよ開封

帰宅して早速開封していきます。

いつものアップルの袋から、少しだけ透けて見えます。

f:id:yuki10k:20171103172205j:plain

相変わらず箱にもすごくこだわっています。

f:id:yuki10k:20171103172210j:plain

フタを開けると Designed by Apple in Clifornia
iPhone Xとのご対面はまだ先でした。

f:id:yuki10k:20171103172217j:plain

説明書をどけるとついにご対面・・!

f:id:yuki10k:20171103172227j:plain

本体の下にはイヤホンと電源ケーブル等が綺麗に収納されています。

f:id:yuki10k:20171103172239j:plain

iPhone 7との比較。
右側がiPhone7です。
やっぱり少しだけ大きくなっています。
重さもiPhone 7と比較すると少しずっしりした感じ。

f:id:yuki10k:20171103172251j:plain

裏面はこんな感じ。
ガラスなので光沢があります。
指紋が付きやすいので何かケースに入れたいところ。

f:id:yuki10k:20171103172303j:plain

少し使ってみて

  • iOS11にしてからiPhone7が少しもっさり気味だったのがサクサクになりました。
  • TouchID(ホームボタン)が無いので、まだ少し手間取る
  • FaceIDは少し遅いけど、対応しているアプリも多く、問題なく使えています。
  • 画面が大きくなって最高!!

値段は跳ね上がりましたが、今のところ満足です
iPhone7では使えなかったポートレートモードも使えるようになったので、これから色々試していきたいと思います。

NEXTGEAR-MICROにメモリを増設

以前、ゲーミングPCを購入したことを↓で書きました。

yuki10.hatenablog.com

やっぱりメモリ8GBは並行で色々開くと少しつらいのでメモリを増設することにしました。

まずは使えそうなメモリを選ぶところから。

NEXTGEAR-MICRO im570 シリーズ(H110) デスクトップゲーミングPCの通販|G-Tune

スペック詳細を見ると、PC4-19200 DDR4が2枚挿せるとのことでした。
最大は16GBx2枚で32GBです。

16GBにするか32GBにするか迷いましたが、以下の理由で16GBにしました。

  • 32GBの在庫が無い または 3万5千円以上となかなか高額
  • 32GBもきっと使わない

というわけで購入したのはこちらのメモリです。

Amazon | CFD販売 デスクトップPC用メモリ PC4-19200(DDR4-2400) 8GBx2枚 288pin (無期限保証)(Crucial by Micron) W4U2400CM-8G | パソコン・周辺機器 | パソコン・周辺機器 通販

メモリは価格変動が結構激しいようで、自分が購入したときから3000円近く安くなっていてショック。

8GBのメモリが既に1枚刺さっているので、8GBx1でいいのかもしれないですが、あまり詳しくないので同じ8GBメモリを2枚セットにしました。

届いたのはこちら。

f:id:yuki10k:20170613003020j:plain

早速ケースをあけていきます。
PCの背面に下の写真のようなネジが2箇所あるので、普通のプラスドライバーでネジを外します。

f:id:yuki10k:20170613003034j:plain

ネジを外したら、手前に引くと簡単に側面のカバーが外れます。

中身はこんな感じでスッキリ。
ファンの横にあるのがメモリスロットです。

f:id:yuki10k:20170613004426j:plain

拡大。
既に1枚刺さっています。

f:id:yuki10k:20170613004448j:plain

刺さっていたメモリを抜いて、今回購入した2枚のメモリを刺します。
結構力強く押さないと、左右のロックがうまくはまりませんでした。

f:id:yuki10k:20170613004456j:plain

カバーを閉じて、再度電源を入れると、うまくメモリが認識していればBIOSの画面が出ますがそのまま進めます。
※メモリが認識されないと起動しないと思うので、その場合は再度、フタをあけてメモリがちゃんと固定されているか確認しなおしです。

無事に16GB認識してくれました!

f:id:yuki10k:20170612230413p:plain

このPCはメモリ増設がしやすくていいですね。
8GBで足りないという方は試して見てください。

※メモリの規格はちゃんと確認しましょう!!ノート用、デスクトップ用やDDR3 / DDR4など色々種類があります。 ※PC側の規格やスロットも事前に確認してから購入しないと、スロットが足りない・・・となりかねないので注意です。

無線ルーターの調子が悪いので買い替えた

BUFFALOのAirStationという無線ルーターを使っていたのですが、頻繁に勝手に再起動がかかるようになってきたので買い替えました。
再起動ぐらいで、と思うかもしれないですが、NETFLIXを見たりしているときに切断されると結構なストレスに。。

まずは職場の人におすすめを聞いたところ、NECAtermという回答ばかりだったので、Atermシリーズで探してみることに。

あまりこだわりはなかったので、以下の要件を満たすもので適当にさがしました。

  • ギガビット有線LAN接続
  • 11ac接続対応

最終的にこちらのモデルにしました。
ビックカメラで5300円ほどでした。

121ware.com

さっそく既存のルーターと取り替えます。
奥のが今まで使っていたルーター
ホコリまみれです・・
4年以上は使っているはずなので、仕方ないといえば仕方ない。
Atermは小さいと聞いていましたが、あまりサイズ感は変わらないです。

設定は、Macでやりました。
WiFiの設定をすると、ブラウザで設定ページが立ち上がるので、プロバイダからのIDとパスワードを入力するだけで簡単に接続できました。
IIJひかりですが、全く問題なし。

実測はこんな感じ。

f:id:yuki10k:20170520171119p:plain

今までよりちょっとはやいかな・・?という程度です。

今までも速度には別に不満はなかったので、これで安定して使えるようになればというところ。
しばらく使って様子を見たいと思います。

機械学習にも使えるゲーミングPCを購入!

なかなか書けずに購入してから半月以上たってしまいましたが、今更ながら書いていきます。

購入の目的

  • 機械学習をちゃんとやってみたい
  • ゲーム
  • 久々にWindowsに触ってみようと思った

購入したモデル

色々調べましたが、最終的にマウスコンピュータのG-Tuneか、ドスパラのGALLERIAで暫く悩んでいました。
元々は、

あたりのスペックを検討していましたが、どうしても15万以上するので二の足を踏んでいました。
そんなときにAmazonのSpringセールを眺めていたら、以下のモデルが20%OFFで販売していたので、即決で購入しました。

Amazon CAPTCHA

購入時の価格は
割引前は120,356円で
割引後は 96,285円でした。

なんとか15万円以下でと考えていたので、かなり安く抑えられて満足しています。

カスタマイズすると割引が効かなくなるので、以下の構成のまま購入しています。

mouse ゲーミング デスクPC G-Tune NM-K5081SHG6-ZBF

  • Corei5 7400
  • メモリ8GB
  • GTX1060 3GB
  • SSD240GB
  • HDD 1TB
  • bluetooth / 無線LAN アダプタ
  • マウス
  • キーボード

ちょっとメモリが少ないので、余裕ができたら16GBか32GBに換装したいと思います。

実際使ってみての感想は以下の通り。

  • 基本SSDなので普通に速い
  • Macほどメモリを食いつぶさないので、大した作業をしないのであればメモリ不足にはならない。
  • 例えばFF14Chromeだけなら余裕です
  • ディスプレイには、以前購入いsたLGの4KディスプレイにDisplayPortで接続しています。

yuki10.hatenablog.com

Windowsは久々なので、少しづつ慣れていきたいと思います。

最後にFF14の最新のベンチマークです。
細かい設定は乗っていませんが、DirectX11の1980x1080 最高品質であれば、ストレス無く遊べると思います。
確か7000以上が非常に快適なので、まだ余裕があります。

f:id:yuki10k:20170515005312p:plain