
JavaエンジニアがKotlinに移行する際、最も危険なのは「Kotlinの文法でJava5の頃の思考で書く」ことです。
RxJava(リアクティブプログラミング)という高い壁を飛び越えようとして、逆に20年前の古典的手法に着地してしまうケースが後を絶ちません。
fun loadUser(callback: (User?) -> Unit) {
api.getUser { user ->
if (user != null) {
database.save(user) {
cache.update(user) {
analytics.track(user) {
callback(user)
}
}
}
} else {
callback(null)
}
}
}
interface OnUserLoadedListener {
fun onLoaded(user: User)
}
fun loadUser(listener: OnUserLoadedListener) {
api.getUser(object : ApiCallback {
override fun onSuccess(user: User) {
database.save(user, object : SaveCallback {
override fun onSaved() {
listener.onLoaded(user)
}
})
}
override fun onError() {
}
})
}
🤔 1. RxJava以前の「古代遺物」がモダンなKotlinを侵食する
RxJavaすら導入されていない現場、あるいは「Rxは難しいから」と避けた結果、以下のような絶滅危惧種がKotlinの皮を被って出現します。
① 独自インターフェースによる「バケツリレー」
interface MyCallback を定義し、それを Activity から Presenter(あるいは ViewModel)、さらに Repository へと引数で渡していくスタイルです。
地獄のポイント: 1つの処理を追うのに3つ以上のファイルを跨ぐ必要があり、デバッグ中に「今どこにいるのか」を見失います。
② AsyncTask の「自力再実装」
Googleが非推奨にした AsyncTask ですら、中身はスレッド管理とコールバックの塊でした。これをKotlinの Thread { ... } と Handler(Looper.getMainLooper()) で自作再現してしまうパターンです。
地獄のポイント: isDestroyed のチェックを忘れ、画面を閉じた後にクラッシュ(NullPointerException)させる「爆弾」を量産します。
③ MutableList を使った共有メモリの恐怖
非同期の戻り値を待てず、外部の MutableList に値を詰め込ませ、別の場所で Timer や Thread.sleep を使って「値が入ったか監視する」という、スレッドセーフを無視した力技です。
🤔 2. なぜ「古代手法」は再生産されるのか?
それは、Javaエンジニアが長年培ってきた「命令型プログラミング」の呪縛です。
「待つ」という概念の欠如: 「処理を止めたらスレッドが死ぬ(UIが固まる)」という恐怖心から、すべてを「終わったらこれを呼べ」という受動的な構造(ハリウッド原則)にしてしまいます。
状態管理の煩雑さ: 古いJavaでは、状態の変化を「通知」する仕組みが乏しかったため、泥臭いフラグ管理やコールバックに頼らざるを得ませんでした。
🤔 3. 歴史の授業:非同期処理の進化系統図
今のAndroid開発者が知っておくべき、技術の「地層」は以下の通りです。

🤔 4. まとめ:レガシーの鎖を断ち切るために
Javaエンジニアの皆さんが持つ「堅牢なクラス設計」の知識は宝です。しかし、「非同期処理の書き方」だけは、一度全て忘れてください。
Kotlinにおける suspend は、ただのキーワードではありません。それは、私たちが10年以上苦しめられてきた「コールバック地獄」という名の迷宮から脱出するための、唯一の出口なのです。






