Kotlinが正式採用されるのを機に、Androidアプリ開発に試しに挑戦してみました。
内容としては、以下の「エンジニアHub 」の記事を試してみました!というお話です。
Android Studio 3.0 Beta 6 が入る
このブログの執筆時点では、インストールをすると「Android Studio 3.0 Beta 6」が入ります。
なお、Webサイト上からインストールした時点ではBeta 5だったのですが、Android Studio を起動したらアップデートを促されまして、Beta 6に更新されました。
エラーが発生する
意気揚々と、Viewを作成してMainActivityのコードをコピペして起動してみたのですが、エラーが発生しました。
Error:(7, 23) Unresolved reference: Handler Error:(14, 32) Type inference failed: Not enough information to infer parameter T in fun <T : View!> findViewById(p0: Int): T! Please specify it explicitly. Error:(14, 63) Unresolved reference: TextView Error:(15, 35) Type inference failed: Not enough information to infer parameter T in fun <T : View!> findViewById(p0: Int): T! Please specify it explicitly. Error:(15, 63) Unresolved reference: Button Error:(16, 34) Type inference failed: Not enough information to infer parameter T in fun <T : View!> findViewById(p0: Int): T! Please specify it explicitly. Error:(16, 61) Unresolved reference: Button Error:(17, 53) Unresolved reference: reset Error:(17, 63) Unresolved reference: Button
(注釈:Unresolved reference: resetは、ViewのIDを間違えただけの私の凡ミスです。)
どうやってエラーを解決したのか、共有したいと思います。
(上級者であれば、すぐ直せるエラーばかりと思いますが。私自身が初心者ですので、あくまで初心者向けの内容です)
1. importがないと動かない
第一の原因として、import が不足していたため、クラスの解決ができておりませんでした。そのため、以下を追加しました。
import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.os.Handler import android.widget.TextView import android.widget.Button
import文を追加して、必要なクラス(モジュール?)を取り込むとエラーが解消されます。
尚、使用していない未使用のモジュールは以下のように薄黒くハイライトされます。ハイライトされたimportは無駄なimportですので、削除しました。
2. findViewByIdの書き方が異なる
第二の原因として、findViewByIdの書き方でエラーが発生しました。以下のように、findViewByIdで取得してasキャストする書き方はうまく動きません。
val timeText = findViewById(R.id.timeText) as TextView val startButton = findViewById(R.id.start) as Button val stopButton = findViewById(R.id.stop) as Button val resetButton = findViewById(R.id.reset) as Button
エラーメッセージを頼りに、以下のように修正したらエラーが解消されました。
val timeText = findViewById<TextView>(R.id.timeText) val startButton = findViewById<Button>(R.id.start) val stopButton = findViewById<Button>(R.id.stop) val resetButton = findViewById<Button>(R.id.reset) // もしくは val timeText = findViewById<View>(R.id.timeText) as TextView
取得してから型をキャストするのではなく、取得時点で型を指定する必要があるみたいです。
完成版コード
エラーを修正したコードを載せておきます。
package <パッケージ名> import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.os.Handler import android.widget.TextView import android.widget.Button class MainActivity : AppCompatActivity() { val handler = Handler() var timeValue = 0 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) //val timeText = findViewById<View>(R.id.timeText) as TextView val timeText = findViewById<TextView>(R.id.timeText) val startButton = findViewById<Button>(R.id.start) val stopButton = findViewById<Button>(R.id.stop) val resetButton = findViewById<Button>(R.id.reset) val runnable = object : Runnable { override fun run() { timeValue++ timeToText(timeValue)?.let { timeText.text = it } handler.postDelayed(this, 1000) } } startButton.setOnClickListener { handler.post(runnable) } stopButton.setOnClickListener { handler.removeCallbacks(runnable) } resetButton.setOnClickListener { handler.removeCallbacks(runnable) timeValue = 0 timeToText()?.let { timeText.text = it } } } private fun timeToText(time: Int = 0): String? { return if (time < 0) { null } else if (time == 0) { "00:00:00" } else { val h = time / 3600 val m = time % 3600 / 60 val s = time % 60 "%1$02d:%2$02d:%3$02d".format(h, m, s) } } }
Kotlinについての所感
まだサンプルを起動しただけですので、Kotlinの深淵には全く触れておりません。
・・・とは言え、サンプルを見ただけでも「return if」は他の言語ではあまりない書き方ですし、目新しさを感じます。 Kotlinに興味が湧いてきました。
ただ、いくつか不満点をあげるとするならば、valとvarは一文字しか違わないので、見間違える気がしてなりません。 あと、関数宣言がfunなのは、しばらく慣れそうもありません。 普通ならfuncだと思いますので、独特です。
更新履歴
- 2024/06/16 デザイン崩れを修正