As the architecture of Android apps becomes more complex, the classes that perform asynchronous information and the classes that use it are separated. In that case, you have to tell another class when you get the data obtained asynchronously, but it is quite troublesome. So, there are various libraries such as AsyncTaskLoader, which is a support library, and libraries that handle event buses (EventBus, RxJava, etc.), but I didn't have much information on how to make primitive callbacks using the interface, so I summarized them. ..
MainActivity ・ Main class -Create an instance of TasksRepository and TasksBackgroundDataSource. -View display functions are also included here for simplicity.
TasksRepository -A class that holds and operates data. -The instance of TasksBackgroundDataSource is acquired at the time of generation. -Throw a data acquisition request to TasksBackgroundDataSource, or receive a callback and throw a display request to MainActivity.
TasksBackgroundDataSource -A class that brings data asynchronously. -The TasksDataSource interface is implemented. ・ (Since writing the process of bringing data from the network makes the process complicated, just set up a separate thread and embed the data)
TasksDataSource -An interface that summarizes the processing relationships of data acquisition.
Task -A data class that manages the acquired values.
(Note) Listed in the reverse order of the above class list for easy understanding.
Define a function to retrieve data and a function called a callback
TasksDataSource
public interface TasksDataSource {
//Function called as a callback
interface LoadTasksCallback {
void onTasksLoaded(List<Task> tasks);
void onDataNotAvailable();
}
//Data acquisition function (It is not necessary to write it separately, but write it all together)
void getTasks(@NonNull LoadTasksCallback callback);
}
Implemented data acquisition function getTasks After getting it, I will call the callback function
TasksBackgroundDataSource
public class TasksBackgroundDataSource implements TasksDataSource {
@Override
public void getTasks(@NonNull final LoadTasksCallback callback) {
final Handler handler = new Handler();
//Thread launch
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
//Request processing from the main thread using Handler (for View update)
handler.post(new Runnable() {
@Override
public void run() {
//Data acquisition
//・
//・
if (tasks.isEmpty()) {
//Processing when there is no data
callback.onDataNotAvailable();
} else {
//Processing when there is data
callback.onTasksLoaded(tasks);
}
}
});
}
});
thread.start();
}
}
Call getTask of TasksBackgroundDataSource, create an instance of LoadTasksCallback as an argument, implement the function you want to call and pass it.
TasksRepository
mTasksBackgroundSource.getTasks(new TasksDataSource.LoadTasksCallback() {
//Processing called after data acquisition (when there is data)
@Override
public void onTasksLoaded(List<Task> tasks) {
MainActivity.showTextMsg(changeTasksToString(tasks));
}
//Processing called after data acquisition (when there is no data)
@Override
public void onDataNotAvailable() {
Log.w("DEBUG_DATA","TaskRepository onDataNotAvailable");
}
});
After all, call this! I'm just throwing an instance that implements the process in the data acquisition function, but the design to realize it is complicated. This is based on Google's MVP sample, but there The presenter called the getTask of the Repository, and when the getTask of the DataSource was called, the callback was called in a string. As the number of acquisition destinations increases, it becomes difficult to understand, so after all it is better to use the library. I tried to summarize the basics for the time being.
Recommended Posts