Usage of executor in android architecture components

拟墨画扇 提交于 2019-12-24 01:48:07

问题


public class UserRepository {
private final Webservice webservice;
private final UserDao userDao;
private final Executor executor;

@Inject
public UserRepository(Webservice webservice, UserDao userDao, Executor executor) {
    this.webservice = webservice;
    this.userDao = userDao;
    this.executor = executor;
}

public LiveData<User> getUser(String userId) {
    refreshUser(userId);
    // Returns a LiveData object directly from the database.
    return userDao.load(userId);
}

private void refreshUser(final String userId) {
    // Runs in a background thread.
    executor.execute(() -> {
        // Check if user data was fetched recently.
        boolean userExists = userDao.hasUser(FRESH_TIMEOUT);
        if (!userExists) {
            // Refreshes the data.
            Response<User> response = webservice.getUser(userId).execute();

            // Check for errors here.

            // Updates the database. The LiveData object automatically
            // refreshes, so we don't need to do anything else here.
            userDao.save(response.body());
        }
    });
}
}

code above is a part from "Guide to app architecture" using architecture components. Inside refreshUser method they fetch data from network using retrofit if data doesn't exists in cache.

My question is: Why do they use an executor for this? Retrofit itself is already capable of running network request asynchronously.

Please clarify what exactly is an Executor and its need in this example for me.


回答1:


Out of the box room doesn't support database access on the main thread so the executor is there to ensure the work is done on a separate thread.

By using the executor they've also opted to use the synchronous retrofit call which will block the executing thread.

In the code you're referencing the executor is a SingleThreadExecutor, this essentially creates a single worker thread to execute its work, which in this case will execute the Room DB operations along with handling the synchronous retrofit call.

This is the link the to executor in the above example. https://github.com/PhilippeBoisney/GithubArchitectureComponents/blob/98e0a048791f18646c730323c242c670c3eaf453/app/src/main/java/com/boisneyphilippe/githubarchitecturecomponents/di/module/AppModule.java#L48

Along with the official docs for newSingleThreadExecutor: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newSingleThreadExecutor()




回答2:


What exactly is an Executor?

An Executor is normally used instead of explicitly creating threads. For example, rather than invoking new Thread(new RunnableTask()).start() for each of a set of tasks, you might use:

Executor executor = someExecutor();  
executor.execute(new Runnable1());
executor.execute(new Runnable2());

Why do they use an executor for this? Retrofit itself is already capable of running network request asynchronously.

They have used it to switch to a background worker thread from the main thread, to perform a database operation, since by default, Room architecture component does not allow queries on the MainThread.

Retrofit is capable of performing async network requests, but they are doing a synchronous network request here instead after which they are just performing a insert operation on local database using Room component.

For more information about Executor framework, you can follow this guide: https://developer.android.com/reference/java/util/concurrent/Executor



来源:https://stackoverflow.com/questions/52164957/usage-of-executor-in-android-architecture-components

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!