• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.recyclerview.widget;
18 
19 import android.os.Handler;
20 import android.os.Looper;
21 
22 import androidx.annotation.NonNull;
23 import androidx.annotation.RestrictTo;
24 
25 import java.util.concurrent.Executor;
26 import java.util.concurrent.Executors;
27 
28 /**
29  * Configuration object for {@link ListAdapter}, {@link AsyncListDiffer}, and similar
30  * background-thread list diffing adapter logic.
31  * <p>
32  * At minimum, defines item diffing behavior with a {@link DiffUtil.ItemCallback}, used to compute
33  * item differences to pass to a RecyclerView adapter.
34  *
35  * @param <T> Type of items in the lists, and being compared.
36  */
37 public final class AsyncDifferConfig<T> {
38     @NonNull
39     private final Executor mMainThreadExecutor;
40     @NonNull
41     private final Executor mBackgroundThreadExecutor;
42     @NonNull
43     private final DiffUtil.ItemCallback<T> mDiffCallback;
44 
AsyncDifferConfig( @onNull Executor mainThreadExecutor, @NonNull Executor backgroundThreadExecutor, @NonNull DiffUtil.ItemCallback<T> diffCallback)45     private AsyncDifferConfig(
46             @NonNull Executor mainThreadExecutor,
47             @NonNull Executor backgroundThreadExecutor,
48             @NonNull DiffUtil.ItemCallback<T> diffCallback) {
49         mMainThreadExecutor = mainThreadExecutor;
50         mBackgroundThreadExecutor = backgroundThreadExecutor;
51         mDiffCallback = diffCallback;
52     }
53 
54     /** @hide */
55     @SuppressWarnings("WeakerAccess")
56     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
57     @NonNull
getMainThreadExecutor()58     public Executor getMainThreadExecutor() {
59         return mMainThreadExecutor;
60     }
61 
62     @SuppressWarnings("WeakerAccess")
63     @NonNull
getBackgroundThreadExecutor()64     public Executor getBackgroundThreadExecutor() {
65         return mBackgroundThreadExecutor;
66     }
67 
68     @SuppressWarnings("WeakerAccess")
69     @NonNull
getDiffCallback()70     public DiffUtil.ItemCallback<T> getDiffCallback() {
71         return mDiffCallback;
72     }
73 
74     /**
75      * Builder class for {@link AsyncDifferConfig}.
76      *
77      * @param <T>
78      */
79     public static final class Builder<T> {
80         private Executor mMainThreadExecutor;
81         private Executor mBackgroundThreadExecutor;
82         private final DiffUtil.ItemCallback<T> mDiffCallback;
83 
Builder(@onNull DiffUtil.ItemCallback<T> diffCallback)84         public Builder(@NonNull DiffUtil.ItemCallback<T> diffCallback) {
85             mDiffCallback = diffCallback;
86         }
87 
88         /**
89          * If provided, defines the main thread executor used to dispatch adapter update
90          * notifications on the main thread.
91          * <p>
92          * If not provided, it will default to the main thread.
93          *
94          * @param executor The executor which can run tasks in the UI thread.
95          * @return this
96          *
97          * @hide
98          */
99         @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
100         @NonNull
setMainThreadExecutor(Executor executor)101         public Builder<T> setMainThreadExecutor(Executor executor) {
102             mMainThreadExecutor = executor;
103             return this;
104         }
105 
106         /**
107          * If provided, defines the background executor used to calculate the diff between an old
108          * and a new list.
109          * <p>
110          * If not provided, defaults to two thread pool executor, shared by all ListAdapterConfigs.
111          *
112          * @param executor The background executor to run list diffing.
113          * @return this
114          */
115         @SuppressWarnings({"unused", "WeakerAccess"})
116         @NonNull
setBackgroundThreadExecutor(Executor executor)117         public Builder<T> setBackgroundThreadExecutor(Executor executor) {
118             mBackgroundThreadExecutor = executor;
119             return this;
120         }
121 
122         private static class MainThreadExecutor implements Executor {
123             final Handler mHandler = new Handler(Looper.getMainLooper());
124             @Override
execute(@onNull Runnable command)125             public void execute(@NonNull Runnable command) {
126                 mHandler.post(command);
127             }
128         }
129 
130         /**
131          * Creates a {@link AsyncListDiffer} with the given parameters.
132          *
133          * @return A new AsyncDifferConfig.
134          */
135         @NonNull
build()136         public AsyncDifferConfig<T> build() {
137             if (mMainThreadExecutor == null) {
138                 mMainThreadExecutor = sMainThreadExecutor;
139             }
140             if (mBackgroundThreadExecutor == null) {
141                 synchronized (sExecutorLock) {
142                     if (sDiffExecutor == null) {
143                         sDiffExecutor = Executors.newFixedThreadPool(2);
144                     }
145                 }
146                 mBackgroundThreadExecutor = sDiffExecutor;
147             }
148             return new AsyncDifferConfig<>(
149                     mMainThreadExecutor,
150                     mBackgroundThreadExecutor,
151                     mDiffCallback);
152         }
153 
154         // TODO: remove the below once supportlib has its own appropriate executors
155         private static final Object sExecutorLock = new Object();
156         private static Executor sDiffExecutor = null;
157 
158         // TODO: use MainThreadExecutor from supportlib once one exists
159         private static final Executor sMainThreadExecutor = new MainThreadExecutor();
160     }
161 }
162