Worker.java revision 11a7c26af63674a21787696e509e9a43d0bd7acf
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, if any. If this value is {@code null}, the 141 * Worker may use the default network. 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 * Override this method to do your actual background processing. 153 * 154 * @return The result of the work, corresponding to a {@link Result} value. If a 155 * different value is returned, the result shall be defaulted to 156 * {@link Result#FAILURE}. 157 */ 158 @WorkerThread 159 public abstract @NonNull Result doWork(); 160 161 /** 162 * Call this method to pass an {@link Data} object to {@link Worker} that is 163 * dependent on this one. 164 * 165 * Note that if there are multiple {@link Worker}s that contribute to the target, the 166 * Data will be merged together, so it is up to the developer to make sure that keys are 167 * unique. New values and types will clobber old values and types, and if there are multiple 168 * parent Workers of a child Worker, the order of clobbering may not be deterministic. 169 * 170 * This method is invoked after {@link #doWork()} returns {@link Result#SUCCESS} 171 * and there are chained jobs available. 172 * 173 * For example, if you had this structure: 174 * 175 * {@code WorkManager.getInstance(context) 176 * .enqueueWithDefaults(WorkerA.class, WorkerB.class) 177 * .then(WorkerC.class) 178 * .enqueue()} 179 * 180 * This method would be called for both WorkerA and WorkerB after their successful completion, 181 * modifying the input Data for WorkerC. 182 * 183 * @param outputData An {@link Data} object that will be merged into the input Data of any 184 * OneTimeWorkRequest that is dependent on this one, or {@code null} if there 185 * is nothing to contribute 186 */ 187 public final void setOutputData(@NonNull Data outputData) { 188 mOutputData = outputData; 189 } 190 191 public final @NonNull Data getOutputData() { 192 return mOutputData; 193 } 194 195 /** 196 * Returns {@code true} if this Worker has been told to stop. This could be because of an 197 * explicit cancellation signal by the user, or because the system has decided to preempt the 198 * task. In these cases, the results of the work will be ignored by WorkManager and it is safe 199 * to stop the computation. 200 * 201 * @return {@code true} if the work operation has been interrupted 202 */ 203 public final boolean isStopped() { 204 return mStopped; 205 } 206 207 /** 208 * Returns {@code true} if this Worker has been told to stop and explicitly informed that it is 209 * cancelled and will never execute again. If {@link #isStopped()} returns {@code true} but 210 * this method returns {@code false}, that means the system has decided to preempt the task. 211 * <p> 212 * Note that it is almost never sufficient to check only this method; its value is only 213 * meaningful when {@link #isStopped()} returns {@code true}. 214 * <p> 215 * @return {@code true} if this work operation has been cancelled 216 */ 217 public final boolean isCancelled() { 218 return mCancelled; 219 } 220 221 /** 222 * @hide 223 */ 224 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 225 public final void stop(boolean cancelled) { 226 mStopped = true; 227 mCancelled = cancelled; 228 onStopped(cancelled); 229 } 230 231 /** 232 * This method is invoked when this Worker has been told to stop. This could happen due 233 * to an explicit cancellation signal by the user, or because the system has decided to preempt 234 * the task. In these cases, the results of the work will be ignored by WorkManager. All 235 * processing in this method should be lightweight - there are no contractual guarantees about 236 * which thread will invoke this call, so this should not be a long-running or blocking 237 * operation. 238 * 239 * @param cancelled If {@code true}, the work has been explicitly cancelled 240 */ 241 public void onStopped(boolean cancelled) { 242 // Do nothing by default. 243 } 244 245 @Keep 246 @SuppressWarnings("unused") 247 private void internalInit( 248 @NonNull Context appContext, 249 @NonNull UUID id, 250 @NonNull Extras extras) { 251 mAppContext = appContext; 252 mId = id; 253 mExtras = extras; 254 } 255 256 /** 257 * @hide 258 */ 259 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 260 public @NonNull Extras getExtras() { 261 return mExtras; 262 } 263} 264