投稿

ラベル(Java)が付いた投稿を表示しています

Java を Kotlin へ

Kotlin については Google の公式ドキュメントが多数あるが、 Kotlin への変換 という Codelabs の片隅にあった文章が、最初に知りたかったことだけが物凄く完結にまとまっていた。最初にこの文章にアクセスできていればと思ったほど。もちろん、Java ベースの Android プログラミングのベースがある人限定の話になるが。 Java Kotlin final オブジェクト val オブジェクト equals() == == === データのみを保持するクラス data クラス コンストラクタでの初期化 init ブロックでの初期化 static フィールドおよび関数 companion object で宣言されているフィールドと関数 シングルトン クラス object 例えば、当初、companion object を見て、「何で Java の static オブジェクトと同じものを、わざわざ名前を変えて companion object とかいう名称にしているんだ?」と思ったが、実は良く考えられているようだ。Java の static オブジェクトの場合はオブジェクト毎の modifier として宣言するのに対して、Kotlin の companion object はクラス内のブロックとして宣言されている。これは可読性の点で優れている。 Kotlin は Java をベースにしながらも、(上の表からは割愛されているが)埋め込みテキストなど、可能な限り、可読性のために Python などのスクリプト系言語の簡潔な表現を取り入れようとしている感じかもしれない。

Android / Java と OpenGL ES 2.0 の要点

以下のような人(要するに僕自身のケースと同じ)を対象にしている: Android / Java のアプリ開発についての一般的な理解はある ImageView.onDraw や SurfaceView による動画ならそれほど苦労せずに理解できた しかし、OpenGL (ES 2.0) のことになると色んな解説やサンプルコードを見ても理解に苦しんで中々はかどらない なぜ OpenGL はわざわざああいうことをするようになっているのか? ImageView.onDraw や SurfaceView による動的グラフィックスなら理解しやすかった人にとって、動画とは、パラパラ漫画のようなものというほとんど無意識的な大前提があるわけだ。パラパラ漫画に限らず、映画やアニメなど、世の中の映像記録方式としては、こちらが圧倒的主流。ImageView.onDraw や SurfaceView の場合も、ループを回して、フレームバッファに次々とコマを描き込むだけ。 ところが、OpenGL はそれを許してくれないので、何か物凄く高度な、GPU のハードウェア的な性能を引き出すために、OpenGL の API を通じて描画する必要があるのかと、勘違いする。実際はそう(高度な GPU のハードウェア的な性能を引き出した上でレンダリングするのが目的の API 体系)ではないので、架空の妄想を相手に戦う羽目になり、決して勝利することができない戦いに挑む形になる。 OpenGL はそもそも、パラパラ漫画的なことをプログラマーが自らやることを想定していない(GPU 側の内部処理として行われる)。その一歩手前の部分(モデリング)を主にするのがプログラマーの仕事。モデルを基にしてラスタライズしてフレームバッファに落し込む処理は、GPU 側が(プログラマーが予め定義したフラグメントシェーダーに従って)内部的に行う形になっている。つまり、プログラマーがすべき仕事の領域がそもそも異っている点に気付かなければならない。 言ってみれば、フレームバッファ描き込みによるパラパラ漫画的動画はチカチカと瞬く GIF アニメみたいなもので、OpenGL はヌルヌル動く Flash アニメーションみたいなもの(Flash ももう過去の遺物だが……)。他にも、ペイント系グラフィック(ビットマップ

Android の OpenGL ES と SurfaceView / GLSurfaceView

イメージ
今さらながら Android の OpenGL ES に初めて手を付けてみた。これまでは ImageView の onDraw のカスタムか、ゲーム的なものでも、2D で SurfaceView の画面を丸ごと FrameBuffer として更新するような使い方しかしてこなかった。ところが今回、ちょっと凝った 2D のマップアプリのようなものを作ることになり、先述の通り従来は ImageView の onDraw カスタムで対処してきたのだが、できれば、SurfaceView か、さらには OpenGL ES 化して、Google Map のようなヌルヌルしたものにできないかと思い、3D 用だと思って敬遠してきた OpenGL ES の領域にまで足を踏み入れてみることにした。 SurfaceView 以前、使ったことがあると言っても、ちょっとした 2D ゲームのサンプルで使った程度であり、非ゲームのアプリに利用するというような場合も含めて SurfaceView 自体を研究したことはなかったので、まずは SurfaceView をいじってみることにした。 レンダリング用スレッドを使用する Activity 側で SurfaceHolder.Callback を implement するなりして、レンダリング用スレッドの生成や終了処理を行う。レンダリング用スレッド中では、SurfaceHolder を通じて Surface への(Canvas の描画命令を使った)描画を行う。 Canvas → SurfaceHolder → Surface という 3 重のバインド構造になっているの( 参考 )で初見では戸惑うかもしれないが、やっていることは Surface(framebuffer のようなもの)へのデータの書き込みである。 val canvas: Canvas = holder.lockCanvas() // Canvas#drawBitmap 等を使った描画処理 holder.unlockCanvasAndPost(canvas) レンダリング用スレッドを使わないで、そのままメイン UI スレッドで同様のことを行うこともできるが、圧倒的に処理が重くなる。SurfaceView を使う意味がない。 SurfaceView を使うこと

LiveData と MutableLiveData の使い分け

イメージ
observe 関係の場合は、できるだけ ViewModel と View(Activity 含む)の関係を疎にして、一方通行の関係がいいと思う。つまり、ViewModel 内部では MutableLiveData 扱いのデータを LiveData にして外側、つまり View 側に対してさらす形である。 private MutableLiveData<T> mData; public LiveData<T> getData() { return mData; } 一方、user action を ViewModel に入力する場合はどうするのがいいか? この場合は、user action の影響を受ける LiveData は、View/Activity からの入力で変化することが当然であるから、上の observe の場合のように MutableLiveData を getter で隠蔽することは冗長である。なので、public な MutableLiveData を getter を介さずに直接さらしてしまえばいいと思う。 public MutableLiveData<T> mData; そうして、当該 MutableLiveData に関する処理を、無理矢理 ViewModel に置かずに、素直に、View/Activity 内で処理を記述するのが、 実は 適切だと思う。 というのも、user action によって処理を分けたいのは、View/Activity 側の都合であって、ViewModel 側の場合ではないケースが考えられるからである。通常、user action を受け付けるのは、Activity が active すなわち、onResume から onPause の間のライフサイクルにおいてである。なので、その間のみ処理を行って、それ以外のタイミングでは処理を停止しているような形にするのが望ましい。そうなると、それらの処理の主となるコードは、Activity 側の各ライフサイクルに応じたメソッドに配置して、処理の結果変更を受ける変数のみ、MutableLiveData として ViewModel 内に所属させておくのがストレートなコード表現になるわけである。 サンプ

Static Singleton vs. Application Subclass

シングルトンは自前の Static Singleton を実装すべきか、Application サブクラスを使うべきか? Application のサブクラスを Singleton 的な目的で使うことはよくある話だが、実際に Static Singleton を使うのか、(Static Singleton の一種である)Application サブクラスを使うのかには、議論の余地があるようだ。 StackOverFlow の議論: Singletons vs. Application Context in Android? によると、Static Singleton 派と Application サブクラス派に分かれていて、両派ともほぼ対等な支持を得ている。 しかし、公式リファレンスには以下のようにある: ★ Note: There is normally no need to subclass Application. In most situations, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), include Context.getApplicationContext() as a Context argument when invoking your singleton's getInstance() method. この記述を見る限り、どちらかというと、Singleton 的なことをしたいのであれば、単に Static Singleton を使う方がお勧めのようだ。global context を使いたいのであれば、Context.getApplicationContext() で得た Context オブジェクトを Singleton の getInstance() で引数として渡せば用が足るとしている。「Singleton 的なもので、さらに処理の中にグローバルコンテキストを扱うものが含まれるから Application を使う必要がある」と考

UML クラス図

クラス クラス名 + メンバー名: 型 ~ メンバー名: 型 - メンバー名: 型 # メンバー名: 型 + メソッド名(引数: 型): 型 ~ メソッド名(引数: 型): 型 - メソッド名(引数: 型): 型 # メソッド名(引数: 型): 型 スコープは +: public; ~: package; -: private; #: protected スタティック変数/メソッドを示す場合はアンダーラインで修飾する。 インスタンス同士の関係 Dependency(依存) independent <- - - - - - - - - - dependent どちらが「依存する側(dependent / client)」で、どちらが「依存される側(independent / server)」なのかを表す。依存する側から依存される側に向かう破線矢印。 Association(関連) label independent <------------------- dependent     1                 1,* 実線で結ばれ、関係名を付す場合には、線の中央の上にテキストを記す。また、多重度(multiplicity)を表す場合には、各ノードの付け根に m..n といった形式で範囲を示す。 さらに、関連性に方向性がある場合には、双方向(bi-directional)か片方向(uni-directional)かによって、矢印で示すことができる。また、自分で自分を参照するような反射的(reflexive)な関連の記述も可能である。 Aggregation(集約) bag ◇------------------- item 集約は関連の中でも特殊なケースで、has-a で表される全体←部分の関係のこと。ただし、合体(Composition)と違って、部分側は全体のライフサイクルに依存せず、独立して存在する。ショッピングバッグに入った色々な野菜のようなもの。 白抜きの菱形で集約先を示す。 Composition(合体) puzzle ◆------------------- piece 合体も関連の中でも特殊なケースで、has-a で表される全体←部分の関係のこと。ただし、集約(Ag

LVMC (a.k.a. MVVM) サンプル

前日の記事「 Android で MVVM ならぬ“LMVC” 」のサンプルコード build.gradle (:app): plugins { id 'com.android.application' } android { compileSdkVersion 30 buildToolsVersion '30.0.3' defaultConfig { applicationId 'com.scaredeer.lvmcsample' minSdkVersion 26 targetSdkVersion 30 versionCode 1 versionName '1.0' } compileOptions { sourceCompatibility 1.8 targetCompatibility 1.8 } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } buildFeatures { dataBinding true } } dependencies { implementation 'androidx.appcompat:appcompat:1.3.0' implementation 'com.google.android.material:material:1.4.0' // https://developer.android.com/jetpack/androidx/releases/lifecycle#java implementation 'androidx.li

Application と ViewModel の使い分けはどうすればいいのか?

Activity か Fragment を基点として「ある程度安定して動けばいいや」的スタイルで Android プログラミングを続けてきたので、Application はたまに使用例に従って採用していただけで、主体的に判断して使用したことはない。それで最近、ボンヤリと、Android プログラミングに関する情報を調べていたら、Activity のライフサイクルに巻き込まれない、 モデル(ビジネスロジック)的なデータは Application で扱う(格納する)べし みたいな話があって、ちょっと気になっていた。 その辺りは特に他のアイデアがなく、自分は Activity や Fragment でそのままデータを持たせていたので、onSaveInstanceState / onRestoreInstanceState で Bundle を使って退避してライフサイクルの輪廻転生をくぐり抜けられるようにしたり、SharedPreferences を使って逐次 Persistent なデータとして退避するなどして、力技で対抗していた。 Application を使えば、もうちょっと楽にできたのかなと思って気にしていたところ、 ViewModel なんてものも存在することを(今さら)知り、Application と ViewModel の使い分けってどうなんだろう? と思った。もちろん、継承関係からしてそもそも存在意義が全然違うのだろうけど、「Activity のライフサイクルの輪廻転生をくぐり抜けて過去・現在・未来の三世を通じた一貫した記憶を保つ」という意味で、Application を使うか ViewModel を使うかということに、どういう違いがあるのだろうかということだ。 まあそもそも、Application の方は、ライフサイクルというよりは、スコープ的なグローバル性やシングルトン性の方がテーマとなるのだろうし、ViewModel の方はライフサイクルまで Activity に巻き添えを食らわないというだけで、あくまでも Activity / Fragment に従属したローカルなインスタンスなんだろうけど。 書いているうちに、全然違うよね〜、誰も疑問に思わないよね〜、という気持ちになってきた……。 Model とは言っても、ViewModel で扱う

HTTP/1.1 Transfer-Encoding: chunked

Web Scraping 用のプログラムを組んでいて、HTTP レベルの Socket プログラムを自前で組むか、Client レベルの処理は言語環境のライブラリーに任せて HTML を解析・処理する程度のものを組むかという、二択問題によく悩む。これまでの経験上、後者の方が敷居が低く取りかかるのに容易であるというメリットがある。一方、一旦何らかの壁にぶち当たると、ブラックボックスのない前者の環境で試行錯誤を進めた方が、心理的にもまさしく“急がば回れ”の典型のような結果となり、トータルで楽になる。 そんなわけで、今回取り組んでいる物件についても、スタートアップは Java の URLConnection で一通り組み上げてしまって、それで問題なく全体的に動くものが出来上がっていたので、そのまま運用していたものだった。ゼロ状態からのスタートとなるプロジェクトでは、まずはどんな形であれ、全体としてちゃんと動くものへと到達できるかどうかが不明な状態なので、「まずは全体としてちゃんと動くもの」まで辿り着くことが何よりも重要である。そのためには、Client レベルのものは Java のコアライブラリーに任せて、Web Scraping にターゲットを絞った方が確実にプロジェクトを成功まで推進することができる。 それでそのまま動くようになったままで運用し続けていて、プログラムには手を入れていなかったのだが、今度、Lanterna を使って GUI 化したりして、使い勝手が向上したので、さらに前から欲しいと考えていた機能を追加したりした。最終的には GUI 化したらしたで CUI の時は気にならなかった処理速度が気になったので、ネットワークからのデータの読み込みをマルチスレッド化するところまで行き着いた。 このネットワーク読み込み処理のマルチスレッド化で、ある問題が表面化したのだった。 どうやら Java の URLConnection は、スレッドセーフではないようなのだ。とはいっても、このプロジェクトに関して言えば、Cookie がスレッド間で共有されていることが問題の核心であり、それを URLConnection 自体がスレッドセーフではないという話に含めていいのかどうかはわからない。ともかく、Cookie が上書きされてしまうのが原因で、サーバー側が付与する JS

Exception の使い処

Perl では Exception のことは気にしないでプログラミングできたので、Java で当初特異に感じたのが Exception の扱いだ。仕様に強制される形で try-catch を行う必要があるという認識で今まで凌いできた。 そもそも CUI でプログラミングしている段階では、例外処理については別段の配慮はせずとも、コンソールに JVM が吐くエラーメッセージが表示されるので、自分でエラーに備える処理を明示的にコーディングする必要はなかった。CUI というのはそういった意味でユーザーとプログラマーが完全に同一レベルの視点で体験を共有しているので、ある意味貴重な環境なのかもしれない。 そういった CUI の貴重な環境の習慣をそのまま引き摺ってしまっていて、GUI で Android のアプリなどを作っていても、例外処理について、標準メソッド側が要求するから受動的に try-catch を記述する程度で、自分から能動的に Exception クラスを用いるという経験があまりなかった。 ところで最近 Web のフォーム送信操作を自動化する Java プログラムを作成していて、想定外のエラーが発生した時、そのエラーがどの段階で出たエラーなのかということがわかった方が、自分自身で利用するだけでなくもしアプリを公開するという前提では、その方が良いと考えた。そこで、各段階で、想定通りではない結果になっていた場合、Exception を発生させるようなコードにすることにした。 当初は字義的に、RuntimeException を使っていた。ところがこれでも「どの段階で発生したのか?」がわかりにくかったので、最終的には IOException を使うことに落ち着いた。 GUI ライブラリーとして Lanterna という ncurses ライクなライブラリーを使っており、コンソールではなく、GUI の表示にエラーメッセージも表示させたいと考えた。当初の RuntimeException だと、どこかでエラーが発生していることがコンソールには表示されるのだが、どの段階で起ったのかが把握しにくく、GUI 側でもどこでキャッチすればいいのかがわかりにくい。そこで IOException にして、GUI 側で catch させることにしたのである。 ネットワークにアク

プログラミング・パラダイム

結局、「オブジェクト指向プログラミング(OOP)」というのは、1) 手続指向は構造化で、2) データは構造体で、ということであり、この両者を、3) 構造化された手続(メソッド)を、構造体(オブジェクト)単位で整理することでまとめた、というだけの話であり、これ以上でもないし、これ以下でもないのではないかと思う。 手続自体は、あくまでも構造化プログラミング的な観点で整理を行なうべきで、これを生半可なオブジェクト指向的観点で整理すると、コードが無茶苦茶になって却って“百害あって一利なし”といっても言い過ぎにはならない気がする。少なくとも、自分の場合はそうである。 そうやって、構造化プログラミング的にすっきりと整えられた個々のコードが、集合して複数のコード群としてそのままそこいらにぶちまけられている時に、手続指向の限界が急にクローズアップされてくる。 この時に整理整頓の“容れ物”として俄かに脚光を浴びることになるのが、構造体(オブジェクト)である。手続のためのコードをそのまま“裸”でそこいらにぶちまけては置かないようにしよう、必ず、構造体に入れられた(カプセル化)状態で置いておくことにしようね、というのが僕流のオブジェクト指向像である。 上のことをちゃんと自覚していないで、「オブジェクト指向スゲー」で何でもかんでもオブジェクト指向のノリを持ち込もうとすると、むしろコードの見通しが悪くなって、あっちへ飛んだり、こっちへ飛んだりと、ダイクストラ先生が「goto は使わないようにしよう」といった時代の事情に逆戻りして、あっちのメソッドこっちのメソッドを飛び回るような、いわば「goto なきスパゲッティ化プログラミング」に陥ってしまう。 新しいコードをスクラッチで組んでいく時、ここは手続指向で素直に、一つ一つの処理を継ぎ足して行ってプログラミングするのが、やはり王道なのではないかと思う。そしてそのコードが伸びるにつれ、(2回以上)多用される同様の処理は、サブルーチンとして分離する。そのことで、「コードをコピー&ペーストして使い回すことを避ける」というのが、構造化プログラミングの単純かつ肝となる原点だと思う。ある処理に関するコードが記述される場所を一元化することで、後に変更の必要が生じた時に、あちこちを修正して回るというようなことは避けないと、例えば、一部を修正し、一部

オブジェクト指向プログラミングと構造化プログラミング

オブジェクト指向プログラミング(OOP)と構造化プログラミング(手続指向)を対立する概念だと思っていたが、どうやら間違っていたようだ。 詳細は別の機会でもあれば書くかもしれないが、両者は共存可能、というか共存させるのが適切だと思った。 この結論に達することで、メソッド定義の private と public、static と dynamic の使い分けもはっきり線引きできるようになったと思う。 構造化プログラミングは static で、そのうちのサブルーチン部分は private、メインルーチンは public。 オブジェクト指向プログラミングは dynamic で、オブジェクトの操作に関するインターフェイスとしてのメソッドは public。 大ざっぱな分け方としてはそんな感じ。

Amateras Modeler

Eclipse (neon) に Amateras Modeler(プラグイン)を追加した。 GEF SDK のインストール(http://download.eclipse.org/releases/neon から GEF をフィルタリングして見つければよい) Amateras Modeler のインストール(http://takezoe.github.io/amateras-update-site/ からインストールすればよい) 使い方は、File > New > other > AmaterasUML > クラス図 で新規作成し、クラスファイルをドロップすれば自動的にクラス図が表示される。