Worker.java revision 3db1e38129d3326eecb27b49f11144fb58cb9765
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 17package androidx.work; 18 19import android.content.Context; 20import android.net.Network; 21import android.net.Uri; 22import android.support.annotation.Keep; 23import android.support.annotation.NonNull; 24import android.support.annotation.Nullable; 25import android.support.annotation.RequiresApi; 26import android.support.annotation.RestrictTo; 27import android.support.annotation.WorkerThread; 28 29import androidx.work.impl.Extras; 30 31import java.util.Set; 32import java.util.UUID; 33import java.util.concurrent.TimeUnit; 34 35/** 36 * The basic object that performs work. Worker classes are instantiated at runtime by 37 * {@link WorkManager} and the {@link #doWork()} method is called on a background thread. In case 38 * the work is pre-empted for any reason, the same instance of Worker is not reused. This means 39 * that {@link #doWork()} is called exactly once per Worker instance. 40 */ 41public abstract class Worker { 42 43 /** 44 * The result of the Worker's computation that is returned in the {@link #doWork()} method. 45 */ 46 public enum Result { 47 /** 48 * Used to indicate that the work completed successfully. Any work that depends on this 49 * can be executed as long as all of its other dependencies and constraints are met. 50 */ 51 SUCCESS, 52 53 /** 54 * Used to indicate that the work completed with a permanent failure. Any work that depends 55 * on this will also be marked as failed and will not be run. 56 */ 57 FAILURE, 58 59 /** 60 * Used to indicate that the work encountered a transient failure and should be retried with 61 * backoff specified in 62 * {@link WorkRequest.Builder#setBackoffCriteria(BackoffPolicy, long, TimeUnit)}. 63 */ 64 RETRY 65 } 66 67 @SuppressWarnings("NullableProblems") // Set by internalInit 68 private @NonNull Context mAppContext; 69 @SuppressWarnings("NullableProblems") // Set by internalInit 70 private @NonNull UUID mId; 71 @SuppressWarnings("NullableProblems") // Set by internalInit 72 private @NonNull Extras mExtras; 73 private @NonNull Data mOutputData = Data.EMPTY; 74 private volatile boolean mStopped; 75 private volatile boolean mCancelled; 76 77 /** 78 * Gets the application {@link Context}. 79 * 80 * @return The application {@link Context} 81 */ 82 public final @NonNull Context getApplicationContext() { 83 return mAppContext; 84 } 85 86 /** 87 * Gets the ID of the {@link WorkRequest} that created this Worker. 88 * 89 * @return The ID of the creating {@link WorkRequest} 90 */ 91 public final @NonNull UUID getId() { 92 return mId; 93 } 94 95 /** 96 * Gets the input data. Note that in the case that there are multiple prerequisites for this 97 * Worker, the input data has been run through an {@link InputMerger}. 98 * 99 * @return The input data for this work 100 * @see OneTimeWorkRequest.Builder#setInputMerger(Class) 101 */ 102 public final @NonNull Data getInputData() { 103 return mExtras.getInputData(); 104 } 105 106 /** 107 * Gets a {@link Set} of tags associated with this Worker's {@link WorkRequest}. 108 * 109 * @return The {@link Set} of tags associated with this Worker's {@link WorkRequest} 110 * @see WorkRequest.Builder#addTag(String) 111 */ 112 public final @NonNull Set<String> getTags() { 113 return mExtras.getTags(); 114 } 115 116 /** 117 * Gets the array of content {@link Uri}s that caused this Worker to execute 118 * 119 * @return The array of content {@link Uri}s that caused this Worker to execute 120 * @see Constraints.Builder#addContentUriTrigger(Uri, boolean) 121 */ 122 @RequiresApi(24) 123 public final @Nullable Uri[] getTriggeredContentUris() { 124 Extras.RuntimeExtras runtimeExtras = mExtras.getRuntimeExtras(); 125 return (runtimeExtras == null) ? null : runtimeExtras.triggeredContentUris; 126 } 127 128 /** 129 * Gets the array of content authorities that caused this Worker to execute 130 * 131 * @return The array of content authorities that caused this Worker to execute 132 */ 133 @RequiresApi(24) 134 public final @Nullable String[] getTriggeredContentAuthorities() { 135 Extras.RuntimeExtras runtimeExtras = mExtras.getRuntimeExtras(); 136 return (runtimeExtras == null) ? null : runtimeExtras.triggeredContentAuthorities; 137 } 138 139 /** 140 * Gets the {@link Network} to use for this Worker. This method returns {@code null} if there 141 * is no network needed for this work request. 142 * 143 * @return The {@link Network} specified by the OS to be used with this Worker 144 */ 145 @RequiresApi(28) 146 public final @Nullable Network getNetwork() { 147 Extras.RuntimeExtras runtimeExtras = mExtras.getRuntimeExtras(); 148 return (runtimeExtras == null) ? null : runtimeExtras.network; 149 } 150 151 /** 152 * Gets the current run attempt count for this work. 153 * 154 * @return The current run attempt count for this work. 155 */ 156 public final int getRunAttemptCount() { 157 return mExtras.getRunAttemptCount(); 158 } 159 160 /** 161 * Override this method to do your actual background processing. 162 * 163 * @return The result of the work, corresponding to a {@link Result} value. If a 164 * different value is returned, the result shall be defaulted to 165 * {@link Result#FAILURE}. 166 */ 167 @WorkerThread 168 public abstract @NonNull Result doWork(); 169 170 /** 171 * Call this method to pass an {@link Data} object to {@link Worker} that is 172 * dependent on this one. 173 * 174 * Note that if there are multiple {@link Worker}s that contribute to the target, the 175 * Data will be merged together, so it is up to the developer to make sure that keys are 176 * unique. New values and types will clobber old values and types, and if there are multiple 177 * parent Workers of a child Worker, the order of clobbering may not be deterministic. 178 * 179 * This method is invoked after {@link #doWork()} returns {@link Result#SUCCESS} 180 * and there are chained jobs available. 181 * 182 * For example, if you had this structure: 183 * 184 * {@code WorkManager.getInstance(context) 185 * .enqueueWithDefaults(WorkerA.class, WorkerB.class) 186 * .then(WorkerC.class) 187 * .enqueue()} 188 * 189 * This method would be called for both WorkerA and WorkerB after their successful completion, 190 * modifying the input Data for WorkerC. 191 * 192 * @param outputData An {@link Data} object that will be merged into the input Data of any 193 * OneTimeWorkRequest that is dependent on this one, or {@code null} if there 194 * is nothing to contribute 195 */ 196 public final void setOutputData(@NonNull Data outputData) { 197 mOutputData = outputData; 198 } 199 200 public final @NonNull Data getOutputData() { 201 return mOutputData; 202 } 203 204 /** 205 * Returns {@code true} if this Worker has been told to stop. This could be because of an 206 * explicit cancellation signal by the user, or because the system has decided to preempt the 207 * task. In these cases, the results of the work will be ignored by WorkManager and it is safe 208 * to stop the computation. 209 * 210 * @return {@code true} if the work operation has been interrupted 211 */ 212 public final boolean isStopped() { 213 return mStopped; 214 } 215 216 /** 217 * Returns {@code true} if this Worker has been told to stop and explicitly informed that it is 218 * cancelled and will never execute again. If {@link #isStopped()} returns {@code true} but 219 * this method returns {@code false}, that means the system has decided to preempt the task. 220 * <p> 221 * Note that it is almost never sufficient to check only this method; its value is only 222 * meaningful when {@link #isStopped()} returns {@code true}. 223 * <p> 224 * @return {@code true} if this work operation has been cancelled 225 */ 226 public final boolean isCancelled() { 227 return mCancelled; 228 } 229 230 /** 231 * @hide 232 */ 233 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 234 public final void stop(boolean cancelled) { 235 mStopped = true; 236 mCancelled = cancelled; 237 onStopped(cancelled); 238 } 239 240 /** 241 * This method is invoked when this Worker has been told to stop. This could happen due 242 * to an explicit cancellation signal by the user, or because the system has decided to preempt 243 * the task. In these cases, the results of the work will be ignored by WorkManager. All 244 * processing in this method should be lightweight - there are no contractual guarantees about 245 * which thread will invoke this call, so this should not be a long-running or blocking 246 * operation. 247 * 248 * @param cancelled If {@code true}, the work has been explicitly cancelled 249 */ 250 public void onStopped(boolean cancelled) { 251 // Do nothing by default. 252 } 253 254 @Keep 255 @SuppressWarnings("unused") 256 private void internalInit( 257 @NonNull Context appContext, 258 @NonNull UUID id, 259 @NonNull Extras extras) { 260 mAppContext = appContext; 261 mId = id; 262 mExtras = extras; 263 } 264 265 /** 266 * @hide 267 */ 268 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 269 public @NonNull Extras getExtras() { 270 return mExtras; 271 } 272} 273