東京タラレバ娘 を読んだ。
本編も面白いけど、おまけ漫画も面白い。
RecyclerView.Adapterは、Item毎にViewTypeを指定することでItem毎にViewHolderを指定出来る。なので「itemが映画ならFilmViewHolderを利用する」とか「itemがドラマならTvDramaViewHolderを利用する」とか「positionが0ならAdViewHolderを利用する」などが出来る。
ただそれをやっていると以下のようにViewHolderのインスタンスを作成するonCreateViewHolder
とViewHolderを利用するonBindViewHolder
がItemViewTypeが増えるたび膨らむ。
public FilmographyAdapter(Context context) { this.context = context; } ... @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { switch (viewType) { case VIEW_TYPE_1: { return new TvDramaViewHolder(LayoutInflater.from(context).inflate(R.layout.row_filmography, parent, false)); } case VIEW_TYPE_2: { return new FilmViewHolder(LayoutInflater.from(context).inflate(R.layout.row_filmography, parent, false)); } default: { throw new IllegalArgumentException("みつからんかった"); } } } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { switch (holder.getItemViewType()) { case VIEW_TYPE_1: { ((TvDramaViewHolder) holder).render(items.get(position)); break; } case VIEW_TYPE_2: { ((FilmViewHolder) holder).render(items.get(position)); break; } default: { throw new IllegalArgumentException("みつからんかった"); } } }
RecyclerView-Binderというのもあって、それを利用すれば上記のようにswitchで頑張る必要は なさそう。ただViewHolder以外に自分でBinderクラスを作らなければならない事, Adapterに継承が必要なことが理由で利用しなかった。
なので、aptの勉強がてら自分で作ってみた。
github.com
さっきのswitch文べったりなコードがこうなる。
public FilmographyAdapter(Context context) { // Binderクラスが自動で生成されるのでそれのインスタンスを持つ this.binder = new FilmographyAdapterViewHolderBinder(context, this); } ... // @ViewHolderでviewTypeとlayoutを指定してあげる void onBindViewHolder( @ViewHolder(viewType = VIEW_TYPE_1, layout = R.layout.row_filmography) TvDramaViewHolder holder, int position) { holder.render(items.get(position)); } void onBindViewHolder( @ViewHolder(viewType = VIEW_TYPE_2, layout = R.layout.row_filmography) FilmViewHolder holder, int position) { holder.render(items.get(position)); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // @ViewHolderで指定されたViewType, layoutを元に // ViewHolderのインスタンスを作成する。 return binder.create(parent, viewType); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { // @ViewHolderで指定されたViewTypeを元に利用するViewHolderのインスタンスを決めて // そのインスタンスにあった onBindViewHolder() を利用する。 binder.bind(holder, position); }
ViewHolderのインスタンスを作成する部分は、僕はいつもこう書いてるだけなので、人間が書く必要はないなと感じた。なので、全部自動生成するようにした。
return new ItemViewHolder(layoutInflater.inflate(R.layout.hogehoge, parent, false));
その結果、ViewTypeが増えれば、 対応したViewHolderとonBindViewHolder(...)
を追加してやるだけになった。
onCreateViewHolder
などが膨らんでしまい書くコードも多いAndroidでサーバなしのA/Bテストを行いたかったが、それらしいライブラリを見つける事が出来なかったので作った。iOSでいうmattt/SkyLabみたいなのです。
振る舞いを変えたい場合はこうする。
new Hanaten(context, "presenter test") .add(10, new Runnable() { @Override void run() { mPresenter.showRed(); } }) .add(20, new Runnable() { @Override void run() { mPresenter.showGreen(); } }) .add(30, new Runnable() { @Override void run() { mPresenter.showBlue(); } }) .start();
返ってくる値を変えたいとかはこうする。
String color = new Splitter<String>(context, "color test") .add(10, "Red") .add(20, "Green") .add(30, "Blue") .split();
github.com
ちゃんとjcenterとかに登録したほうがいいかなーと思いつつjitpack.io使ってる。
HeaderやFooterで各々ViewHolderを作る必要もなかったので、それすらないシンプルなAdapterです。
github.com
// HeaderFooterAdapterを継承する class MovieAdapter extends HeaderFooterAdapter<ItemViewHolder> { private List<String> movies; private LayoutInflater layoutInflater; MovieAdapter(LayoutInflater layoutInflater) { this.layoutInflater = layoutInflater; } void setMovies(List<String> movies) { this.movies = movies; notifyDataSetChanged(); } // ItemのViewHolderを作成して返す @Override protected ItemViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) { return new ItemViewHolder( this.layoutInflater.inflate(R.layout.row_movie, parent, false)); } // ItemのViewHolderを利用する @Override protected void onBindItemViewHolder(ItemViewHolder holder, int position) { holder.setName(this.movies.get(position)); } // Itemの数を返す @Override protected int getAdapterItemCount() { return movies.size(); } } // ActivityなどでAdapterをセットする前にHeaderViewとFooterViewをセットする MovieAdapter adapter = new MovieAdapter(layoutInflater); adapter.setHeaderView(headerView); adapter.setFooterView(footerView); recyclerview.setAdapter(adapter);
Github上で人に対してコメントや説明をする時、送信する前に自分の書いた日本語を見返す。見返すときに「相手は何が聞きたいのか?」と「聞きたいことの答えが伝わるか」って考えながら見返す。それが分かるように書かれてあればそのまま送信するし、伝わらないかもなと思ったら書き直す。そういうのはコードにも言えると思うけど、日本語でも重要だと思う。
というのが、だいぶ前に書いたブログの下書きに残ってたんだけど、この本にも似たような事が書かれてた。
PMJPのSlackで紹介されていたので読んだ。新卒とかが読むと良さそうな感じだった。
ウニバーという概念があると聞き、行くしかないと思ったので行ってきた。
ウニの食べ比べがあり、産地別に出てきた。「違いなんてわかるはずない」「そんなに舌が肥えていない」とか思ってたけど、案外わかってウニはすごい。
最後ににぎりが出来てたけど、ウニもうまかったけど肉が異常にうまかった。解説されたけど、うまさのあまり知性が破壊されてしまったようで忘れてしまった。
ウニバー、存在してくれてありがとう
— ひさいち (@hisaichi5518) 2016年3月28日
だいぶ盛り上がって面白かった。みんなでわいわい議論したり出来る勉強会いい。
実家に帰るつもりだったけど、親が二人ともインフルエンザにかかっているらしく帰れなくなって泊まる場所がなくなった。
京都まで来たので実家に泊まるつもりでいたら、親がインフルエンザになったらしく家に帰れなくなってウケた
— ひさいち (@hisaichi5518) 2016年3月25日
なので、同じく宿がない人達で銭湯と仮眠室が合体したところに行った。俺だけ掛け布団なくて寒くて最悪だった。あと屋上にある風呂が臭かった。
銭湯にあったドブみたいな臭いの風呂
— ひさいち (@hisaichi5518) 2016年3月27日
京都界隈の人間として誘われていたので、行くしかないという気持ちで花見した。京都水族館前の公園でやっていた。桜自体は少し咲いてた。そのあとは、鴨川に行って色々あって銭湯と仮眠室が合体したところに行った。変なおじさんがいっぱいいて恐怖したけど、朝まで生きて京都から出ることができた。
@shiyakeita インリンオブジョイトイみたいにM字開脚して寝てるおじさんいた
— ひさいち (@hisaichi5518) 2016年3月27日
京都は最高