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