Retrofit使ってて詰まったところとか
詰まったところを共有していこうかなって。
しょっぱながJsonArrayから始まってた
stackoverflow.com
Jsonがいきなり[]から始まる奴のパースの仕方。
Kくんも困ってたこの問題、自分はちゃんとこれで解決できた。
てか、普通に{}で始めてほしい...
叩いたAPIがリダイレクトするのを無視したい
final OkHttpClient client = new OkHttpClient(); client.setFollowRedirects(true);
これをRestAdapterにセットしてあげれば行ける。
ちょっと闇感じる。
てか、リダイレクトして帰ってきた奴はfailureに行くのかな?
ここら辺よくわかなんないけど、パス!
JsonのKeyが動的に変わる
stackoverflow.com
普通に変わるやつをMapで置けばいいだけだった。
Map#keysetか何かでKey一覧取れるし、Valueもちゃんととれていい感じ。
Map最強。
Gsonに少し詳しくなった。
GETの時のデフォルトのパラメータのセット
@GET(Const.API.NEW_LIST + "?order=new") void getNewList(CallbackNewrList> callback);
GETの時はURLに含められるけど、POSTの時はどうすればいいんだろう。
前は@QueryParamみたいなのがあったらしい。
今はどうなんだろう。
パラメータにNull渡した時の挙動
POSTでもGETでもQueryやFieldにNull渡した時はRequestに含まれないらしい。
非常に便利。
必須パラメータだけ@NonNullアノテーションつけたら非常に良い運用ができそうな気がした。
最後に
RetrofitなしじゃAPIを叩けない体になった。
Retrofitマスターに俺はなる!!!!!
addViewしていったら追加したViewが横に並んでいき、横いっぱいになったら改行してくれるViewGroup
「addViewしていったら追加したViewが横に並んでいき、横いっぱいになったら改行してくれるViewGroup」
が必要になったからちょっと作ってみた。
gist.github.com
作ってて思ったんだけど、onLayout内の指定の仕方、なぜrightとbottomを基準にしたんだろう。
ま、これでやりたいこと出来てるからいいけど。
こういうViewGroup、なんだかんだ必要な時が多いから便利そう。
おわり
ScrollViewの中に入れても平気なListView
LinearLayoutにaddViewしただけのようなパフォーマンスを発揮するListView
Viewの再利用とは何だったのか
使い道がわからない
stackoverflow.com
コレ、パクった
onMeasureでカラム数とViewのサイズとってsetMeasuredDimensionやってもうまく行かなかったけど、確かにLayoutParamに直接指定すればうまくいった。
アレだ、なんかのモック作ってる時に最初はListViewでやってたけど、注文が多くてScrollViewで囲わないといけなくなって、今更LinearLayoutに置き換えてaddViewするのめんどいって時に使える。
おすすめしないけど。
おわり
ADF2015に参加してた
参加してた
recruit-jinji.jp
これに参加してましたー。
いろいろ一回り二回りしたらスタッフ扱いになりイベントを少しだけ手伝う要因になりました。
ワタシ、ナイテイノタメニ、ガンバル
スタッフだったのであまり各セッションの内容を知らず、実はあまり書けることがないというのが...
Application Developer Festival 2015参加録 | でぶだるまは赤だるま
ココらへんとかに書いてくれてあります。
最終日のハッカソン
これだけはスタッフにも参加が許された唯一のものでした。
優勝しました
賞品もらいました
あざっす
発表スライドがこちら
www.slideshare.net
GoogIe(ぐーぎぃ)というサービスっぽい何かを作った感じです。
iWatchという卑猥なデバイスを作り、iTurnという卑猥なデバイスを作り。
多分近々動画も出てくるのではないかなと思うのでそのうち紹介しますー
最後に
ま、なんというか、リクルート主催のイベントなんですが、リクルートという単語をあまり聞かず、そういう就活イベントみたいな感じではない所、かなり良かったです。
あと、公式サイトに書いてあった内容は達成出来てると思いますねー。
強いAndroiderに出会えました!!!!!
成功するか絶妙なラインで攻めてたあたり"第一回"という感じがして面白かったです。
エンジニアのことを少しわかって、色んな所からうまく手を回している人事の努力が一番成功に近づいた要因だと思いますね! (ナイテイクダサイ)
春の長期インターンの時(ナイテイクダサイ)や今回のイベントの前日に見た目のクマから(ナイテイクダサイ)色々と心配なところや(ナイテイクダサイ)遅くまで(ナイテイクダサイ)(ナイテイクダサイ)(ナイテイクダサイ)(ナイテイクダサイ)(ナイテイクダサイ)(ナイテイクダサイ)(ナイテイクダサイ)(ナイテイクダサイ)(ナイテイクダサイ)(ナイテイクダサイ)
楽しかった、ありがとう、リクルート
仕方ないから留年して来年もイベントに参加しようと思います!!!!!!!
ではではー
Android TVアプリ開発について(╬ ꒪⌓꒪)
書いた
AndroidTVアプリの開発事情 | リクルートライフスタイル開発者ブログ
これ、書いたんですが、もう少しだけ噛み砕いた言葉で色々と書きたい!!!!
とりあえず、
Android TV入門 - Qiita
amyu/androidtv-Leanback at createRecommendationContentProvider · GitHub
この2つ読めば開発できるかなーって。
色々ごちゃごちゃ書いたんですが、一番良かったのがサンプルを読むことだったという。
で、一番注意して欲しいRecommendation CardにFocusが当たった時の処理はContentProvider作成して、取り出さないと表示されないという点ぐらいです。
凝ったことをしない、ゲームを作らないぐらいだったらサクッと実装できるかなって思います。
激おこな点
Youtube API使用できないっぽいんですよー。
激おこ。
Android TVなのに!!!!
Issue 4585 - gdata-issues - YouTube Android Player API INTERNAL_ERROR on Google TV - Server-side issues and feature requests - Google Project Hosting
GoogleTVに来てたIssueなんですが、追加でAndroidTVも無理だよ的な雰囲気なことが書いてあって...
はー。
(╬ ꒪⌓꒪)
最後に
Google TV化しなければいいね!!!!!!
追記
YouTube Player API Reference for iframe Embeds - YouTube — Google Developers
コレ使えば行ける。
(実装したくない)
Recruit Holdings Winter Internshipに参加してた
インターンに参加した
RECRUIT HOLDINGS-リクルートホールディングス-|インターンシップサイト
コレっす。
参加して15万もらえて、優勝したら100万もらえる超良いインターン。
優勝こそは出来なかったものの夏のインターンと比べると非常に良かったのでそこら辺をつらつらと。
選考
そもそも15万出るわけですから、選考もAndroidエンジニアコースの方はかなり適切な選考方法でした。
プロコン優秀者がアプリエンジニアに簡単にクラスチェンジできるわけでなく、プログラミングテストの他に各分野ごとでテストを行って、選考させてたのは非常に良かったです。
で、Androidは4人しか通らず、全10~14?チーム中2チームしかいなかったのは、まぁまぁ予想できた感。
お題
5つぐらいある中から好きなのをお題にして作れといった感じで、これも夏と比べると良いかなーって。
インターンでやるなら全部自由にというよりこういったほうが適切だなと感じました。
別にアイデアソンをやってるわけではなく、技術力とかとかをアピールしやすい環境でしたねー。
こんなん作った
内部の処理もSquare様〜って感じなライブラリ構成になっていて、
・ButterKnife
・Retrofit
・Picasso
などなど。
基本的にViewは全部手作りで、唯一と言っていいぐらいで使ったのがHorizontalなListViewでした。
いや、ホント結構自作View作りまくって...
一応5.0を対象に作っているんですが、4系でもレイアウトが崩れないようちゃんと2種類に分けてdrawable構成もしていたりとなかなか頑張りが伺えます。
共有のページもURLをクリック後、アプリが入ってる場合はアプリへ、ソレ以外だったらブラウザで表示といったイケイケな感じになってます。
素晴らしい!!!!
個人的にTagを付ける部分の画面が少し気合が入ってたり。
かなり気持ちいいUIを目指してDrag処理を書いてたりするので色々と満足してます。
開発途中はこんな感じだった
投稿する画面、実はDelete処理もできるんですよーーー!
開発途中だった時のGifですが...
今回作ったアプリの切り出せる部分のViewは適当に切り出してギッパブに上げようかなーって思ってます。
他にも隠れた部分に色々とこだわってたりしてなかななか書き起こせない感じ。
動画中にない画面が実は3画面ぐらいあったりするんですよー。
さらに見て欲しいのがアイコン。
GoogleMapのパクリだと思ってもらっても構わないんですが、ちゃんと強調したい部分に微妙に影がついてたりするんですよ!
よく出来てますよね、1時間半ぐらいで作ってくれました。
ネットワーク通信周りはもう一人のチームメンバーに作ってもらってました。
かなり良い設計をしてくれたおかげで、超絶楽に済んだかんじです。
で、サーバ側、APIを作ってくれたチームメンバーも優秀で叩きやすいAPI設計になっていて超良かったです。
はー良いメンバーでよかった。
ま、要望としては、Webとスマホを同じ基準では評価できないから分けて評価して欲しかったなーって感じっすね、
参加してみて
やはりWebすごいなーというのが第一印象。
優勝したチームのフロントサイドの出来の良さにかなり感動しました。
できることの幅広さ、世に出てる知見の数が圧倒的に違うなーという。
ここ最近つらつらと感じている、「Androidは最終的にWebになるのかなー」というのを再び考えさせられるほどでした。
結局、現状WebViewオンリーなWebアプリ移植がイケてない理由って
・iOSとデザインガイドライン、操作方法違うのに統一できるわけがない
・カクつく
とかだと思うんですよ。
この2点も結局、Android用にWebで作られたアプリなら上に書いた奴はクリアできるし、「カクつく」も最終的にはハードやブラウザがクリアしてくるんじゃないかなと。
すると、世に出てる数多くのWebアプリの知識群やライブラリ群にネイティブなAndroid開発が対抗できるのかなーって考えちゃうんです。
話し変わるんですが、つい先日「Google for モバイルアプリ ~ Googleと切り開くアプリビジネスの未来」というGoogleのイベントに参加してきたんです。
その時に聞いた話、あまり書けないので残念なのですが、ホントにWebが変わろうとしてるんだなーというのをヒシヒシ感じました。
そういうのを聞いたり見たりしているとJavaでのAndroid開発がいつまで持つのか、というのが非常に気になってくるところで。
ゲームUnity分野以外にフロントWebもやらないとまずいなーって感じました まる
最後に
間違えなくうちのチームが一番良かった!!!!!!!!!!
DragShadowBuilder使った時にonDragで取れる座標について
30分悩んで解決できたことの共有
あまりスマートじゃないのでもっと良い方法があったら教えて下さいー
onDragで取れる座標
onDragから帰ってくるDragEventではgetXとgetYの座標をとれるメソッドがあります。
しかしこのDragEvent、startDragしたView内の座標しか取れないんです(たぶん) ちがった追記に有り
例えば、この赤枠にあるListView内の子ViewでstartDragした場合、この赤枠内だけの座標しか取れませんでした。
例えば、Dragした状態で右方向にずらすとTouchが追えなくなり、DragEventが帰ってこなくなります。
するとy座標で判定していた部分が機能しなくなり...
悩ましかったです。
全部渡せばいいじゃん!
"DragEvent、startDragしたView内の座標しか取れない"
と書いたとおり、渡した部分のView内の座標しか取れないので...
ということは、親Viewを渡して、DragShadowBuilder#onDrawShadowで子Viewをdrawして上げればいいじゃないか!
というふうになったわけです。
するとこんな感じ。
private class DragShadow extends View.DragShadowBuilder { View childView; public DragShadow(View parent, View child) { super(parent); childView = child; } @Override public void onDrawShadow(@NonNull Canvas canvas) { childView.draw(canvas); } @Override public void onProvideShadowMetrics(@NonNull Point shadowSize, @NonNull Point shadowTouchPoint) { int height = childView.getHeight(); int width = childView.getWidth(); shadowSize.set(width, height); shadowTouchPoint.set(width / 2, height / 2); } }
こうすることにより、子Viewを保持しているでっかなViewに対して座標を取得することが出来るようになりました。
パチパチー
最後に
ほーよく出来てる。
追記
@amyu_san あれっ。素直に childItem.startDrag() 、ListView.setOnDragListener() するのではダメなの?
— HaRu (@h6a_h4i) February 8, 2015
あああああああああああああ、これえええええええええ。
Listenerを親Viewに対してつければそりゃ中で動いてるものをとれるうううう...
startDragしたやつしかOnDragListenerをセットできないという謎の迷信に囚われてた...
はああああああああ。
無駄な30分を過ごした。
@amyu_san 気になったから勉強がてら書いてみたコード → https://t.co/2jMtm51lBV
— HaRu (@h6a_h4i) February 8, 2015
ありがたきGistはこちら
ほんとありがとうございました
RegionとPathを用いた特定の部分のTouchEventの取り方
前回書いたViewの記事の補足を少し。
なんか日本語の記事が見つからなかったので書いちゃう。
TouchEventの制御
そもそもViewのonTouchEventが呼ばれる時はpaddingやTouchDelegateをしない限り四角いViewを触った時に呼ばれるはずです。
例えば、上のようなViewがあるとして、望まれる挙動は空白の白い部分にはClickListenerを付けず、六角形の内部のみClickListenerを付けイベントを飛ばしたいと考えると思います。
そんな時役に立つのがRegionでした。
IngressAchievements/AchievementView.java at develop · amyu/IngressAchievements · GitHub
このViewを見てもらえればさくっと伝わるんですが、
/** * Pathを引きながらRegionにいろいろとセットする処理 */ for (int i = 0; i < VERTEX_NUM + 1; i++) { double cos = Math.cos(Math.toRadians(60 * i + 30)); double sin = Math.sin(Math.toRadians(60 * i + 30)); double innerX = centerX + radius * cos; double innerY = centerY + radius * sin; mInnerPath.lineTo((float) innerX, (float) innerY); } mRectF.setEmpty(); //RectFに対してPathの外枠の座標をセットする mInnerPath.computeBounds(mRectF, true); mRegion.setEmpty(); mClipRegion.setEmpty(); //ClipとなるRegionに外枠の座標をセットしたRectFをセットする mClipRegion.set((int) mRectF.left, (int) mRectF.top, (int) mRectF.right, (int) mRectF.bottom); //Regionに対してPathとClipとなるRegionをセットする mRegion.setPath(mInnerPath, mClipRegion);
と言った感じでRegionをセットしていきます。
続いてonTouchEvent内での処理。
@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: //Regionに触られた部分の座標が含まれているか if (mRegion.contains((int) event.getX(), (int) event.getY())) { if (mOnClickListener == null) { return true; } //何事もなかったらイベントを飛ばしてあげる mOnClickListener.onClick(this); } break; } return false; }
と言った感じで実装できます。
最後に
Unityに浮気したい。
ではではー
IngressAchievementsっていうView作った
IngressAchievements
amyu/IngressAchievements · GitHub
コレ作ったはいいんですけど、ライブラリ化するのとか作ってる最中にめんどくさくなってきて。
そのうち暇になったらまた進化させます。
六角形の部分のTouchEvent
Regionに六角形のPathをセットして、ViewのonTouchEventでRegionの範囲内の時にListenerを叩くといった感じ。
で、上の画像のView構成は、AchievementViewというView拡張したViewをIngressListViewで表示してる感じなんです。
その時に、Viewの重なった部分のTouchEventが被るため、onInterceptTouchEventを常にfalseを返してViewにTouchEventがいくようにしるんですよー。
ViewGroup#addViewの時の処理
ViewGroupのコード読んだら
public void addView(View child, int index, LayoutParams params){ //... }
の処理でaddViewが終わっていた。
なので、色々と変えたいんだったらこんな感じかな?
@Override public void addView(View child, int index, LayoutParams params) { if (!(child instanceof AchievementView)) { throw new IllegalArgumentException("AchievementView以外が来てるよーーーーー"); } ((AchievementView) (child)).setOnClickListener(mOnClickListener); super.addView(child, index, params); }
これだけ書いておけば、addView(View child)でも勝手にいい感じになりますね。
AttributeSetを始めてちゃんと使った
ライブラリ化した時に使う側とファイル名が被らないようにしないといけないっぽい。
今は
View名_attrs.xml
にしてるけどちゃんとした命名規則があるんだったら知りたいな。
六角形の描画
60度ずつの変化のため、sinとcosの値を定数で持っておけばよかったと後悔。
のちのちに汎用性を持たせたかったと言い訳を...
それぞれの絶妙な計算
IngressListViewで並べるときやAchievementViewリサイズするときになんだかんだ結構計算してるですよー。
ほんと理系でよかった。
できてない所
AchievementViewに画像をセットすることが出来るんですけど、これバグの塊で。
onSizeChangedでセットする画像のBitmapのリサイズ処理が走るんですけど、IngressListViewでたくさんAchievementViewが入ってる時、すべてのAchievementViewでリサイズで処理が走りOOMで落ちるという。
ココらへんちゃんとImageViewとかのコードよんだほうがいいっすね。
はー。
最後に
使い道がないViewがまた世に生まれてしまった...
ではではー