0

Following on from this discussion:

Android AsyncTask API deprecating in Android 11.What are the alternatives?

I need a method for storing values inside the Task Runner. For example, if I am adding values to a list, they will only exist within the task runner and then somehow disappear at the end of the task. Is there a way to permanently store values. I am using the exact same class as the thread above:

TaskRunner taskRunner3 = new TaskRunner();
        taskRunner3.executeAsync(new TaskRequest(elevationURL), (data3) -> {
            TaskRunner taskRunner4 = new TaskRunner();
            taskRunner4.executeAsync(new ElevationTaskParser(data3), (data4) -> {
                LatLng prev = null;
                List<LatLng> pointsToAlertAt = new ArrayList<>();
                double gradient;
                boolean previousLess = true;
                for (LatLng curr : data4.keySet()) {
                    PolylineOptions polylineOptions = new PolylineOptions();
                    if (prev == null) {
                        prev = curr;
                        continue;
                    }
                    gradient = calculateGradient(data4.get(prev), data4.get(curr));
                    if (gradient > ELEVATION_ALERT_VALUE && previousLess) {
                        previousLess = false;
                        pointsToAlertAt.add(curr);
                    } else if (gradient <= ELEVATION_ALERT_VALUE) {
                        previousLess = true;
                    }

In the code above, pointsToAlert is the list that I want to make as a private field of my activity class, but its items become null at the end of the task. Thanks for having a look!

1 Answers1

0

You could use ViewModel and LiveData. Observe the liveData from your activity. Update the liveData in your viewModel from the task runner after the list has been composed. I would do something like this inside your viewModel.

public MutableLiveData<List<LatLng>> pointsToAlert = new MutableLiveData();

void runTask() {
    TaskRunner taskRunner3 = new TaskRunner();
    taskRunner3.executeAsync(new TaskRequest(elevationURL), (data3) -> {
        TaskRunner taskRunner4 = new TaskRunner();
        taskRunner4.executeAsync(new ElevationTaskParser(data3), (data4) -> {
            LatLng prev = null;
            List<LatLng> pointsToAlertList = new ArrayList<>();
            double gradient;
            boolean previousLess = true;
            for (LatLng curr : data4.keySet()) {
                PolylineOptions polylineOptions = new PolylineOptions();
                if (prev == null) {
                    prev = curr;
                    continue;
                }
                gradient = calculateGradient(data4.get(prev), data4.get(curr));
                if (gradient > ELEVATION_ALERT_VALUE && previousLess) {
                    previousLess = false;
                    pointsToAlertList.add(curr);
                } else if (gradient <= ELEVATION_ALERT_VALUE) {
                    previousLess = true;
                }
            }
            pointsToAlert.postValue(pointsToAlertList);
        });
    });
}

Then in your activity onCreate, you can observe this liveData

viewModel.pointsToAlert.observe(MyActivity.this, new Observer<List<LatLng>>() {
        @Override
        public void onChanged(List<LatLng> latLngs) {
            // Update recyclerview with the list of items
        }
    });

If at all you don't want to use a ViewModel, you could maintain a static list and update it accordingly. But beware, that has many caveats. Or you could use database

odifek
  • 180
  • 13
  • So to clarify, does the observer check for updates. My application is using maps so I have methods that will call runTask and update the list in onMapsReady. Will the observer check that the list has been updated later on? Because initially it's always empty in onCreate as my app is getting the list from user input. – Shrimat Kapoor Aug 10 '20 at 09:27
  • 1
    @ShrimatKapoor Whenever you update the list, you have to create a new copy of the list and post it to the liveData. That way, the observer gets notified automatically. Yes. It's reactive. You don't need to check it manually. – odifek Aug 10 '20 at 16:06
  • Ah ok. Would you recommend a way for me to append the values to my mutable live data list rather than copy the whole thing? This is because I want to run the method multiple times and don't want to discard values already stored in the list. – Shrimat Kapoor Aug 10 '20 at 21:53
  • Also, when does the viewmodel activity end. For example, I want to store all the latlngs in a list in my main activity after each observer call and then once the runTask method is complete, I want to run some other code. But what I notice is that when I access my list that I was trying to update, it's empty. And then in the next call when I run the view model, the list gets updated then. How do I know when the viewmodel, runtask ends? – Shrimat Kapoor Aug 12 '20 at 22:06
  • Essentially I am having problems with knowing when the task runner has completed running in the background. The code is not running sequentially, so where would I write the next piece of code once this part is complete? Because if I don't then the list is always empty in my main activity, even if I make it live. Or should I make a mutable live data in my activity and put an observer on that too?? – Shrimat Kapoor Aug 19 '20 at 09:55
  • I don't really get what you mean. When you use LiveData, you should get updated whenever there is a new data. – odifek Aug 20 '20 at 13:40
  • Talk about appending to a list, if that's what you want, then I'd advice maintain this mutable list separately. After updating it, you could simply post it again to the LiveData. That way, you don't have to copy the list over and over again. – odifek Aug 20 '20 at 13:42
  • I did try maintaining a mutable list, however, it was cleared/empty once the task runner was complete. – Shrimat Kapoor Aug 20 '20 at 22:24