我目前正在查看以下指南:https://developer.android.com/topic/libraries/architecture/guide.html

networkBoundResource类:

// ResultType: Type for the Resource data
// RequestType: Type for the API response
public abstract class NetworkBoundResource<ResultType, RequestType> {
    // Called to save the result of the API response into the database
    @WorkerThread
    protected abstract void saveCallResult(@NonNull RequestType item);

    // Called with the data in the database to decide whether it should be
    // fetched from the network.
    @MainThread
    protected abstract boolean shouldFetch(@Nullable ResultType data);

    // Called to get the cached data from the database
    @NonNull @MainThread
    protected abstract LiveData<ResultType> loadFromDb();

    // Called to create the API call.
    @NonNull @MainThread
    protected abstract LiveData<ApiResponse<RequestType>> createCall();

    // Called when the fetch fails. The child class may want to reset components
    // like rate limiter.
    @MainThread
    protected void onFetchFailed() {
    }

    // returns a LiveData that represents the resource
    public final LiveData<Resource<ResultType>> getAsLiveData() {
        return result;
    }
}

我在这里对线程的使用感到困惑。
为什么在这里将@MainThread应用于networkIO?
另外,为了保存到数据库中,将应用@WorkerThread,而使用@MainThread来获取结果。

默认情况下,使用辅助线程进行NetworkIO和本地db交互是不好的做法吗?

我还在检查以下演示(GithubBrowserSample):https://github.com/googlesamples/android-architecture-components
从线程的角度来看,这使我感到困惑。
该演示使用执行程序框架,并为networkIO定义了一个具有3个线程的固定池,但是在演示中,仅为一个调用定义了一个工作任务,即FetchNextSearchPageTask。所有其他网络请求似乎都在主线程上执行。

有人可以阐明理由吗?

最佳答案

看来您有一些误解。

通常,从主线程(UI)调用网络永远是不可能的,但是除非您有大量数据,否则从主线程中的DB中获取数据可能是好的。这就是Google的例子。

1.



首先,由于Java 8,您可以使用lambda语法创建一些接口(interface)(所谓的“功能接口(interface)”)的简单实现。这就是NetworkBoundResource中发生的情况:

            appExecutors.diskIO().execute(() -> {
                saveCallResult(processResponse(response));
                appExecutors.mainThread().execute(() ->
                        // we specially request a new live data,
                        // otherwise we will get immediately last cached value,
                        // which may not be updated with latest results received from network.
                        result.addSource(loadFromDb(),
                                newData -> result.setValue(Resource.success(newData)))
                );
            });

第一个任务(processResponsesaveCallResult)在diskIO Executor提供的线程上进行调度,然后从该线程将其余工作调度回Main线程。

2.







事实并非如此。在主线程上仅创建结果包装程序,即LiveData<ApiResponse<RequestType>>。网络请求是在其他线程上完成的。这不容易看到,因为Retrofit库用于完成所有与网络相关的繁重工作,并且很好地隐藏了此类实现细节。不过,如果您查看将Retrofit封装为LiveDataLiveDataCallAdapter,则可以看到Call.enqueue实际上是异步调用(由Retrofit内部调度)。

实际上,如果不使用“分页”功能,则该示例根本不需要networkIO Executor。 “分页”是一个复杂的功能,因此使用显式的FetchNextSearchPageTask来实现,这是我认为Google示例做得不太好的地方:FetchNextSearchPageTask不会重用processResponse的请求解析逻辑(即RepoRepository),而只是假设它是微不足道的(现在是,但是谁知道 future ...)。此外,没有将合并作业调度到diskIO Executor上的安排,这也与其余响应处理不一致。

07-24 18:52
查看更多