MTU-Dining/app/src/main/java/com/thebrokenrail/mtudining/activity/task/Task.java
2024-02-18 00:41:47 -05:00

119 lines
2.7 KiB
Java

package com.thebrokenrail.mtudining.activity.task;
import java.util.ArrayList;
import java.util.List;
/**
* An asynchronous task (usually a network call).
*/
public abstract class Task<E> {
/**
* Current status of the task.
*/
public enum Status {
NOT_STARTED,
IN_PROGRESS,
DONE,
ERROR
}
private Status status = Status.NOT_STARTED;
/**
* Last time when {@link #start()} was called.
*/
private Long lastStart = null;
/**
* Start task.
*/
public void start() {
lastStart = System.currentTimeMillis();
status = Status.IN_PROGRESS;
result = null;
startImpl(lastStart);
// Update Listeners
sendDataToListeners();
}
/**
* Implementation of {@link #start()}.
* @param id Unique id for each call of {@link #start()}
*/
protected abstract void startImpl(long id);
/**
* Currently stored result (or null if none).
*/
private E result = null;
/**
* Store result.
* @param id ID from {@link #startImpl(long)}
* @param obj Result (or null if error)
*/
protected void done(long id, E obj) {
// Check ID
if (lastStart == null || id != lastStart) {
// Ignore
return;
}
// Store
result = obj;
// Update Status
if (obj == null) {
// Error
status = Status.ERROR;
} else {
// Done
status = Status.DONE;
}
// Update Listeners
sendDataToListeners();
// Ignore Future Responses From This API Call
lastStart = null;
}
/**
* Event listener.
*/
public interface Listener<E> {
/**
* Handle task update.
* @param status The task's status
* @param result The task's result (or null if none)
*/
void update(Status status, E result);
}
/**
* Stored event listeners.
*/
private final List<Listener<E>> listeners = new ArrayList<>();
/**
* Add new listener and send existing data to it.
* @param listener The new listener
*/
public void addListener(Listener<E> listener) {
if (!listeners.contains(listener)) {
listeners.add(listener);
}
}
/**
* Send data to all listeners.
*/
public void sendDataToListeners() {
for (Listener<E> listener : listeners) {
listener.update(status, status == Status.DONE ? result : null);
}
}
/**
* Remove listener.
* @param listener The listener to remove
*/
public void removeListener(Listener<E> listener) {
listeners.remove(listener);
}
}