简体   繁体   中英

Stop running livedata task on activity stop

I'm trying to understand a right way to work with viewmodel & livedata. I created a simple app which started timer when activity start. When activity destroyed - timer continues running and on restart activity created a second timer and now we have two running timers - it's a potential memory leak? How a right way to stop our "task" on stop\destroy activity?

My code:

MainActivity.java

public class MainActivity extends AppCompatActivity {

private ActivityMainBinding mActivityMainBinding;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mActivityMainBinding = ActivityMainBinding.inflate(getLayoutInflater());
    setContentView(mActivityMainBinding.getRoot());

    MainActivityViewModel mainActivityViewModel =
            new ViewModelProvider(this).get(MainActivityViewModel.class);

    Observer<Integer> liveDataObserver = integer ->
            mActivityMainBinding.tvCounter.setText("Elapsed : "+integer+ " s");
    mainActivityViewModel.getLiveData().observe(this, liveDataObserver);

    getLifecycle().addObserver((LifecycleEventObserver) (source, event) ->
            Log.d("mylog", event.name()));

} }

MainActivityViewModel.java

public class MainActivityViewModel extends ViewModel {

private MutableLiveData<Integer> mutableLiveData = new MainActivityLiveData<>();

private static int BEGIN_AFTER = 1000, INTERVAL = 5000;
private static int counter = 0;

public MainActivityViewModel() {
    startTimer();
}

private void startTimer() {
    Timer timer = new Timer();

    timer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            Log.d("mylog", timer.toString() + " " + ++counter);
            mutableLiveData.postValue(counter);
        }
    }, BEGIN_AFTER, INTERVAL);
}



public MutableLiveData<Integer> getLiveData() {
    return mutableLiveData;
} }

MainActivityLiveData.java

public class MainActivityLiveData<T> extends MutableLiveData<T> {

@Override
protected void onActive() {
    Log.d("mylog", "onActive");
}

@Override
protected void onInactive() {
    Log.d("mylog", "onInactive");
}}

You need to stop the timer inside onClear() of viewModel. for that you have to make it a global variable.

public class MainActivityViewModel extends ViewModel {
    private MutableLiveData<Integer> mutableLiveData = new MainActivityLiveData<>();
    private  Timer timer = new Timer();
    private static int BEGIN_AFTER = 1000, INTERVAL = 5000;
    private static int counter = 0;
    public MainActivityViewModel() {
        startTimer();
    }
    private void startTimer() {
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                Log.d("mylog", timer.toString() + " " + ++counter);
                mutableLiveData.postValue(counter);
            }
        }, BEGIN_AFTER, INTERVAL);
    }
    public MutableLiveData<Integer> getLiveData() {
        return mutableLiveData;
    }
    @Override
    protected void onCleared() {
        super.onCleared();
        stopTimer();
    }
    private void stopTimer(){
        if(timer != null) {
            timer.cancel();
            timer.purge();
            timer = null;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM