Предотвращает ли сопрограмма сборщик мусора? - PullRequest
0 голосов
/ 12 июля 2020

Я видел учебники, в которых запись в Room выполнялась в сопрограмме, запущенной с использованием viewModelScope, поэтому она отменяется при уничтожении ViewModel. Но я хочу, чтобы данные записывались в любом случае. Итак, я хочу запустить эту сопрограмму в области видимости, которая не зависит от жизненного цикла Activity.

class MyApplication : Application() {
  val applicationScope = CoroutineScope(SupervisorJob())
}

Верно ли, что если я запустил длительную сопрограмму в ViewModel с использованием этой области видимости ViewModel не будет разрешено собирать мусор до завершения сопрограммы, даже если Activity уничтожено?

1 Ответ

0 голосов
/ 12 июля 2020

Верно. Запуск длительной сопрограммы отовсюду сохранит объекты, на которые она ссылается, до ее завершения или отмены.

Вот почему рекомендуется использовать viewModelScope внутри ViewModel и lifecycleScope в действиях и фрагментах. Потому что они знают, как отменить эти задания.

https://developer.android.com/topic/libraries/architecture/coroutines

Но если вы не ссылаетесь на свое действие или контекст (который на самом деле является самим действием), они не протечет.


   CoroutineScope(SupervisorJob())
            .launch { 
                // activity.getString(R.string.something) // Memory leak!
                applicationContext.getString(R.string.something) // Memory leak on applicationContext but not on activity. That's fine.

            }
. . .
   }

По крайней мере, так я ожидал, что это будет работать. Но, кажется, происходит неожиданное поведение, когда вы делаете там withContext(NonCancellable). См. https://github.com/Kotlin/kotlinx.coroutines/issues/1061.

Короче говоря, напишите это так, чтобы не было ссылок на Activity и другие объекты, которые ссылаются на Activity, что является хорошей практикой. В противном случае ожидайте утечки. Я бы сказал то же самое, если вы ссылаетесь на любые viewmodel объекты внутри сопрограммы.

...