安卓架构 组件 网络线程

2022-09-02 04:37:35

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

网络绑定资源类:

// 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 和本地数据库交互是不是不好的做法?

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

有人可以澄清理由吗?


答案 1

看来你有一些误解。

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

1.

该演示使用执行器框架,并为networkIO定义了一个具有3个线程的固定池,但是在演示中,只有一个调用定义了一个工作线程任务,即FetchNextSearchPageTask。

首先,从Java 8开始,您可以使用lambda语法创建某些接口(所谓的“功能接口”)的简单实现。这是在 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)))
                );
            });

首先,任务 ( 和 ) 被安排在 由 提供的线程上,然后从该线程将其余的工作安排回主线程。processResponsesaveCallResultdiskIOExecutor

2.

为什么@MainThread在这里申请networkIO?

所有其他网络请求似乎都在主线程上执行。

事实并非如此。仅结果包装器,即 在主线程上创建。网络请求在不同的线程上完成。这并不容易看到,因为改造库用于完成所有与网络相关的繁重工作,并且它很好地隐藏了这些实现细节。不过,如果你看一下将改造包装成一个的LiveDataCallAdapter,你可以看到使用的是Call.enqueue,这实际上是一个异步调用(由改造内部安排)。LiveData<ApiResponse<RequestType>>LiveData

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


答案 2

推荐