MeWrite Docs

Application Not Responding (ANR)

AndroidアプリがメインスレッドをブロックしてUIが応答しなくなった場合

概要

ANR(Application Not Responding)は、AndroidアプリがメインスレッドでUIの更新を5秒以上ブロックした場合に発生します。

エラーメッセージ

Application Not Responding

[app name] isn't responding. Do you want to close it?

原因

  1. メインスレッドでの重い処理: ネットワーク、DB、ファイルI/O
  2. デッドロック: スレッド間のロック待ち
  3. 長いループ処理: 大量データの同期処理
  4. BroadcastReceiverのタイムアウト: 10秒以内に処理が完了しない

解決策

1. Coroutineで非同期処理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class MyViewModel : ViewModel() {

    fun fetchData() {
        viewModelScope.launch {
            // バックグラウンドで実行
            val data = withContext(Dispatchers.IO) {
                repository.fetchFromNetwork()
            }
            // UIの更新はメインスレッドで
            _uiState.value = data
        }
    }
}

2. WorkManagerで長時間処理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class DataSyncWorker(
    context: Context,
    params: WorkerParameters
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        return try {
            syncData()
            Result.success()
        } catch (e: Exception) {
            Result.retry()
        }
    }
}

// 実行
WorkManager.getInstance(context)
    .enqueue(OneTimeWorkRequestBuilder<DataSyncWorker>().build())

3. RxJavaでスレッド切り替え

1
2
3
4
5
6
repository.getData()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe { data ->
        updateUI(data)
    }

4. StrictModeで検出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// デバッグ時のみ有効
if (BuildConfig.DEBUG) {
    StrictMode.setThreadPolicy(
        StrictMode.ThreadPolicy.Builder()
            .detectDiskReads()
            .detectDiskWrites()
            .detectNetwork()
            .penaltyLog()
            .build()
    )
}

5. 大量データは分割処理

1
2
3
4
5
6
7
8
suspend fun processLargeData(items: List<Item>) {
    items.chunked(100).forEach { chunk ->
        withContext(Dispatchers.Default) {
            processChunk(chunk)
        }
        yield()  // 他のCoroutineに譲る
    }
}

6. BroadcastReceiverは軽量に

1
2
3
4
5
6
7
8
9
class MyReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        // 重い処理はWorkManagerに委譲
        val workRequest = OneTimeWorkRequestBuilder<HeavyWorker>()
            .setInputData(workDataOf("key" to intent.action))
            .build()
        WorkManager.getInstance(context).enqueue(workRequest)
    }
}

Android の他のエラー

最終更新: 2025-12-09