このエントリーは 名言Advent Calendar 2015の16日目のエントリです。
名言
貴様は臣下を救うばかりで導く事をしなかった 王の欲の形を示す事もなく、道を見失った臣下を捨て置き、 ただ一人ですまし顔のまま小奇麗な理想とやらを思い焦がれていただけよ
王とは、誰よりも鮮烈に生き、もろ人を見せる姿を指す言葉 全ての勇者の羨望を束ね、その道標として立つ者こそが王! 故に、王とは孤高にあらず
このエントリーは 名言Advent Calendar 2015の16日目のエントリです。
貴様は臣下を救うばかりで導く事をしなかった 王の欲の形を示す事もなく、道を見失った臣下を捨て置き、 ただ一人ですまし顔のまま小奇麗な理想とやらを思い焦がれていただけよ
王とは、誰よりも鮮烈に生き、もろ人を見せる姿を指す言葉 全ての勇者の羨望を束ね、その道標として立つ者こそが王! 故に、王とは孤高にあらず
以下のライブラリ群をGradleに追加。AsyncTaskLoader周りはokHttpとRxを使い、Observer周りはottoのEventBusを使って通知のやり取りをする。
こちらも参考に。たぶん前の投稿のスライドと同じ所属の方の作。ありがたや。
パッケージ名 | 役割 |
---|---|
entities | 各ドメインで扱うデータクラスを配置 |
events | EventBusを通して発火するイベントクラスを配置 |
fragments | Fragmentを配置 |
managers | 多様なデータを扱うコントローラを配置 |
models | 各ドメインモデルを配置 |
network | 外部との通信が発生するモジュールを配置 |
utils | ユーティリティー群 |
views | Viewに関連するモジュールを配置 |
package me.rei_m.kotlinmvcsample.managers import java.util.HashMap /** * 各Modelのインスタンスを管理する */ public class ModelLocator private constructor() { companion object { private val showcase = HashMap<Tag, Any>(); public enum class Tag { ATND, } public fun register(tag: Tag, model: Any): Unit { showcase.put(tag, model) } public fun get(tag: Tag): Any = showcase[tag]!! } }
// ModelLocatorにModelの参照を登録
ModelLocator.register(ModelLocator.Companion.Tag.ATND, AtndModel());
package me.rei_m.kotlinmvcsample.entities import java.io.Serializable /** * Atndのイベント情報を保持するデータクラス. */ public data class AtndEventEntity(val id: Int, val title: String) : Serializable
package me.rei_m.kotlinmvcsample.network import com.squareup.okhttp.CacheControl import com.squareup.okhttp.HttpUrl import com.squareup.okhttp.OkHttpClient import com.squareup.okhttp.Request import me.rei_m.kotlinmvcsample.entities.AtndEventEntity import org.json.JSONObject import rx.Observable import java.net.HttpURLConnection /** * Atnd Apiへの接続部分を定義する. */ public final class AtndApi private constructor() { companion object { /** * Atnd APIへのリクエストを行いAtndEventのEntityを返すObservableを作成する. */ public fun request(): Observable<AtndEventEntity> { return Observable.create({ t -> // リクエストのURLを作成. val url = HttpUrl.Builder() .scheme("https") .host("api.atnd.org") .addPathSegment("events") .addQueryParameter("keyword_or", "google,cloud") .addQueryParameter("format", "json") .build() val request = Request.Builder() .url(url) .cacheControl(CacheControl.FORCE_NETWORK) .build() // リクエスト開始. val response = OkHttpClient().newCall(request).execute() if (response.code() == HttpURLConnection.HTTP_OK) { // 正常に取得できたら、パースしてonNextでObserverに流す. val responseJson = JSONObject(response.body().string()); val eventCount = responseJson.getInt("results_returned") if (0 < eventCount) { val events = responseJson.getJSONArray("events") for (i in 0..eventCount - 1) { val e = events.getJSONObject(i).getJSONObject("event"); t.onNext(AtndEventEntity(e.getInt("event_id"), e.getString("title"))) } } } else { // エラーの場合はレスポンスコードをThrowableにつめて投げる t.onError(Throwable(response.code().toString())) } t.onCompleted() }) } } }
package me.rei_m.kotlinmvcsample.models import me.rei_m.kotlinmvcsample.entities.AtndEventEntity import me.rei_m.kotlinmvcsample.events.AtndLoadedEvent import me.rei_m.kotlinmvcsample.events.EventBusHolder import me.rei_m.kotlinmvcsample.network.AtndApi import rx.Observer import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers import java.util.* import me.rei_m.kotlinmvcsample.events.AtndLoadedEvent.Companion.Type as EventType /** * Atndに関する情報を管理するドメインモデル. */ public class AtndModel { /** API読込中など処理中か判定するフラグ */ public var isBusy = false private set /** アテンドのイベント情報を保持するリスト */ public val atndEventList = ArrayList<AtndEventEntity>() /** * AtndのAPIからイベント情報を取得し、内部に保持する. */ public fun fetch() { // ビジー状態の場合は処理終了. if (isBusy) { return } // ビジー状態にする isBusy = true // APIリクエストのオブザーバーを作成 val observer = object : Observer<AtndEventEntity> { override fun onNext(t: AtndEventEntity?) { // リストに追加する. atndEventList.add(t!!) } override fun onCompleted() { // onCompletedを受け取ったら完了のLoadedEventを発火する EventBusHolder.EVENT_BUS.post(AtndLoadedEvent(EventType.COMPLETE)) } override fun onError(e: Throwable?) { // onErrorを受け取ったらエラーのLoadedEventを発火する EventBusHolder.EVENT_BUS.post(AtndLoadedEvent(EventType.ERROR)) } } // AtndのAPIにリクエストを飛ばしてModelへの配信を開始する AtndApi.request() .onBackpressureBuffer() .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .finallyDo({ // 必ずビジー状態を解除する. isBusy = false }) .subscribe(observer) } }
package me.rei_m.kotlinmvcsample.fragments 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.AdapterView import android.widget.ListView import com.squareup.otto.Subscribe import me.rei_m.kotlinmvcsample.R import me.rei_m.kotlinmvcsample.entities.AtndEventEntity import me.rei_m.kotlinmvcsample.events.AtndEventClickEvent import me.rei_m.kotlinmvcsample.events.AtndLoadedEvent import me.rei_m.kotlinmvcsample.events.EventBusHolder import me.rei_m.kotlinmvcsample.managers.ModelLocator import me.rei_m.kotlinmvcsample.models.AtndModel import me.rei_m.kotlinmvcsample.views.adaptors.AtndEventListAdapter import me.rei_m.kotlinmvcsample.events.AtndLoadedEvent.Companion.Type as EventType import me.rei_m.kotlinmvcsample.managers.ModelLocator.Companion.Tag as ModelTag /** * AtndEventをリスト表示するFragment. */ public class AtndEventListFragment : Fragment() { /** ListViewのアダプター */ private var mListAdapter: AtndEventListAdapter? = null companion object { /** * ファクトリ. */ fun newInstance(): AtndEventListFragment { return AtndEventListFragment() } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mListAdapter = AtndEventListAdapter(activity, R.layout.list_item_atnd_event) } override fun onDestroy() { super.onDestroy() mListAdapter = null } override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = inflater!!.inflate(R.layout.fragment_atnd_event_list, container, false) val listView = view.findViewById(R.id.list_atnd_event) as ListView listView.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id -> // リスト内の項目がクリックされたらクリックイベントを発火. val atndEventEntity = parent?.adapter?.getItem(position) as AtndEventEntity EventBusHolder.EVENT_BUS.post(AtndEventClickEvent(atndEventEntity)) } // リストビューにアダプターをセット listView.adapter = mListAdapter return view } override fun onResume() { super.onResume() // EventBus登録 EventBusHolder.EVENT_BUS.register(this); // AtndModelとリストビューに表示中のイベント数を取得 val atndModel = ModelLocator.get(ModelTag.ATND) as AtndModel val displayedCount = mListAdapter?.count!! if (displayedCount != atndModel.atndEventList.size) { // 表示済の件数とModel内で保持している件数をチェックし、 // 差分があれば未表示のイベントがあるのでリストに表示する mListAdapter?.clear() mListAdapter?.addAll(atndModel.atndEventList) mListAdapter?.notifyDataSetChanged() } else if (displayedCount === 0) { // 1件も表示していなければイベント情報を取得する atndModel.fetch() } } override fun onPause() { super.onPause() // EventBus登録解除 EventBusHolder.EVENT_BUS.unregister(this); } @Subscribe @SuppressWarnings("unused") public fun onAtndEventLoaded(event: AtndLoadedEvent) { // ModelからLoad完了のイベントを受け取った時の処理 when (event.type) { EventType.COMPLETE -> { // 読み込みが正常に完了したらModel内のイベント情報をアダプターにセットして再描画する val atndModel = ModelLocator.get(ModelTag.ATND) as AtndModel mListAdapter?.clear() mListAdapter?.addAll(atndModel.atndEventList) mListAdapter?.notifyDataSetChanged() } EventType.ERROR -> { // エラー表示する } } } }
GitHub - rei-m/Kotlin_mvc_sample
転職して新たなMacBookが支給されたけど、セットアップするときにあれ何入れてたっけ?となったので自分用のメモ。(USキーボード向け)
brew cask install iterm2
Top of Screen
にRowsを40
にしておく。iTerm2を開くとモニター上段が表示領域になるbrew install tmux
ショートカットキー | HexCode | 動作 | tmux のコマンド |
---|---|---|---|
Ctrl Shift ] | 0×2 0x6e | 次のWindowに移動 | Ctrl b n |
Ctrl Shift [ | 0x2 0x70 | 前のWindowに移動 | Ctrl b p |
Ctrl N | 0x2 0x63 | 新しいWindowを開く | Ctrl b c |
Ctrl Shift % | 0x2 0x25 | Windowを左右分割 | Ctrl b % |
Ctrl ] | 0×2 0x6f | 次のPaneに移動 | Ctrl b o |
brew install go brew install peco brew install ctags brew install nodebrew brew install rbenv brew install elixir brew cask install java なんかほかあれば
brew cask install atom
ctrl+b , I
でプラグインをインストールする## 11/7(土) 9:00 東京駅集合 9:32 東京駅発 | かがやき507 11:46 富山駅着 昼食取る 13:02 富山駅発 14:17 飛騨古川着 古民家チェックイン 15:00 飲食物買い出し。 15:30 スケジュール確認して開発開始 19:00頃 出前で夕飯 23:00頃 初日は軽く宴。聖地で氷菓観るw ## 11/8(日) 食事以外は基本開発 ## 11/9(月) 朝食後開発追い込みと発表準備 10:50頃 成果発表LT。5分から10分 11:30頃 LT終了。チェックアウト。開発はここまで。 12:00 〜 高山の方までいって軽く観光して名古屋回りで帰還
【前編】CTO不在で、開発組織改善に着手! 一休のエンジニアが語る苦悩の1年 / 飲み会で探るエンジニアのホンネ #naoya_sushi 編
【後編】CTO不在で、開発組織改善に着手! 一休のエンジニアが語る苦悩の1年 / 飲み会で探るエンジニアのホンネ #naoya_sushi 編
package me.rei_m.kotlinsample; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.View; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
Convert Java File to Kotlin File
が追加されていているのでこれを選択します。すると、Kotlinへのコンバートが開始されます。package me.rei_m.kotlinsample import android.os.Bundle import android.support.design.widget.FloatingActionButton import android.support.design.widget.Snackbar import android.support.v7.app.AppCompatActivity import android.support.v7.widget.Toolbar import android.view.View import android.view.Menu import android.view.MenuItem class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val toolbar = findViewById(R.id.toolbar) as Toolbar setSupportActionBar(toolbar) val fab = findViewById(R.id.fab) as FloatingActionButton fab.setOnClickListener(object : View.OnClickListener { override fun onClick(view: View) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG).setAction("Action", null).show() } }) } override fun onCreateOptionsMenu(menu: Menu): Boolean { // Inflate the menu; this adds items to the action bar if it is present. menuInflater.inflate(R.menu.menu_main, menu) return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. val id = item.itemId //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true } return super.onOptionsItemSelected(item) } }
build.gradle
にKotlinでビルドするための設定が追加されるので、この状態でビルドをかけて実行します。
build.gradle
を開いてdependentciesにextensionsを追加します。buildscript { ext.kotlin_version = '0.14.451' repositories { mavenCentral() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version" <- これを追加 } }
MainActivity.kt
を開いてimportを追加します。syntheticから後ろはxmlの名前です。import kotlinx.android.synthetic.activity_main.* import kotlinx.android.synthetic.content_main.*
findViewById
を使わなくてもViewのコンポーネントを参照できるようになります。content_main.xml
のTextView
のテキストをActivity
から書き換えてみましょう。参照するためにはIDが必要なのでxmlを開いて適当にTextView
にidを追加します。ここではhello
としています。MainActivity.kt
に戻り、findViewByIdを使っているところを書き換えてみましょう。override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // val toolbar = findViewById(R.id.toolbar) as Toolbar // setSupportActionBar(toolbar) setSupportActionBar(this.toolbar) // val fab = findViewById(R.id.fab) as FloatingActionButton // fab.setOnClickListener(object : View.OnClickListener { this.fab.setOnClickListener(object : View.OnClickListener { override fun onClick(view: View) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG).setAction("Action", null).show() } }) // TextViewを書き換える処理を追加 this.hello.text = "Hello Kotlin !!" }
findViewById
を使っていたところはimport
したことでthis
から参照できるようになりました。わかりやすくthis
を書いてますが、もちろん無くても動きます。これでビルドして動かしてみましょう。TextView
の表示が変わったはずです。
<AppCompatButton android:id="@+id/open_hogehoge" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="なんか開く" />
<android.support.v7.widget.AppCompatButton android:id="@+id/open_list" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Open sample of listView" />