I came across an issue while building my live app.
Example 1 shows the situation when I open my main activity for the first time, the viewModelScope.launch in my MainActivityViewModel works as expected, however when I open the second activity and close the current activity (main activity) and then open the main activity again the viewModelScope.launch does not work because the viewModelScope is not active.
Example 2 shows the situation when I open my main activity for the first time, the viewModelScope.launch in my MainActivityViewModel works as expected, however when I open the second activity and NOT close the current activity (main activity) and then open the main activity again the viewModelScope.launch continues with the previous work and also starts a new work.
I am not sure if that is somehow related to this issue, however, I am using Dagger-Hilt for dependency injection.
My goal here is to find out how to launch the viewModelScope.launch every time when I open my main activity and what causing the issue (Example 1).
Secondly, find out how to stop the viewModelScope.launch (Example 2) when I am opening the second activity without closing the current activity (main activity).
Example 1 - Activity (Java)
@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
private MainActivityViewModel viewModel;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
...
viewModel = new ViewModelProvider(this).get(MainActivityViewModel.class);
viewModel.testOneViewModelScopeMA();
binding.btnSecondActivity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startSecondActivityIntentWithFinishCurrentActivity(MainActivity.this);
// startSecondActivityIntentWithOutFinishCurrentActivity(MainActivity.this);
}
});
...
private void startSecondActivityIntentWithFinishCurrentActivity(Context _context) {
Intent intent = new Intent(_context, SecondActivity.class);
_context.startActivity(intent);
finish();
}
Example 1 - ViewModel (Kotlin)
@HiltViewModel
class MainActivityViewModel @Inject constructor(
private val mainActivityRepository: MainActivityRepository,
@IoDispatcher private val ioDispatcher: CoroutineDispatcher,
@MainDispatcher private val mainDispatcher: CoroutineDispatcher,
@DefaultDispatcher private val defaultDispatcher: CoroutineDispatcher
) : ViewModel() {
...
fun testOneViewModelScopeMA() {
Timber.d("-> testOneViewModelScope, " +
"\nviewModelScope is active: ${viewModelScope.isActive}")
viewModelScope.launch {
try {
var count = 0
while (true) {
delay(1000L)
count += 1
Timber.d(
"-> testOneViewModelScope, " +
"\nviewModelScope is active: ${viewModelScope.isActive} " +
"\noutput: $count "
)
}
} catch (e: CancellationException) {
Timber.e(
"-> testOneViewModelScope, " +
"\nviewModelScope is active: ${viewModelScope.isActive} " +
"\nCancellationException: \n${e.localizedMessage}"
)
throw e
} catch (ex: Exception) {
Timber.e(
"-> testOneViewModelScope, " +
"\nviewModelScope is active: ${viewModelScope.isActive} " +
"\nException: \n${ex.localizedMessage}"
)
}
}
}
Example 2 - Activity (Java)
@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
private MainActivityViewModel viewModel;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
...
viewModel = new ViewModelProvider(this).get(MainActivityViewModel.class);
viewModel.testOneViewModelScopeMA();
binding.btnSecondActivity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// startSecondActivityIntentWithFinishCurrentActivity(MainActivity.this);
startSecondActivityIntentWithOutFinishCurrentActivity(MainActivity.this);
}
});
...
private void startSecondActivityIntentWithOutFinishCurrentActivity(Context _context) {
Intent intent = new Intent(_context, SecondActivity.class);
_context.startActivity(intent);
}
Example 2 - ViewModel (Kotlin) - the same as Example 1 ViewModel
Let separate your issues
You want to launch a coroutine in ActivityA, every time you open it (newly created and/or go back from other activities). If these, put a call to your view model in ActivityA#onResume. Because
Activity#onCreateis called only one time when the your application creates the activityYou want to cancel your coroutine in Activity A, when you leave it to navigate to other activities.