我正在使用Workmanager在我的应用中实现并行背景上传/下载功能。除了工人同时执行太多作业外,一切效果都很好,并且手机变得无反应,直到事情变下来。我想加入10个任务,并让WM执行2并并行,直到完成所有10个任务。工人似乎并行执行5-10。我不知道该怎么做。我只使用一个螺纹执行器尝试了自己的配置,但没有任何区别。如何一次约束执行的作业数量?我正在使用1.0.0-rc01。
您可以使用自定义Configuration
来定义要同时执行的Worker
s的数量。在您的Application.onCreate()
中这样的东西。有关更多信息,请阅读有关如何使用自定义配置初始化WorkManager
的信息。
val config = Configuration.Builder()
.setExecutor(yourExecutor)
.build()
WorkManager.initialize(context, config)
i测试此示例代码并为我工作而没有任何错误,10并行执行节点(.setExecutor(Executors.newFixedThreadPool(10))
)用于下载文件,而无需任何滞后并冻结UI线程:我使用implementation 'android.arch.work:work-runtime:1.0.0-beta02'
。在您的AndroidManifest.xml
上:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<application
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="de.stocard.stocard.workmanager-init"
android:enabled="false"
tools:replace="android:authorities"/>
</application>
在App.java
中:
Configuration configuration = new Configuration.Builder()
.setExecutor(Executors.newFixedThreadPool(10))
.build();
WorkManager.initialize(getApplicationContext(), configuration);
在MainActivity.java
中:
OneTimeWorkRequest MyWorkA = new OneTimeWorkRequest.Builder(MyWorkA.class)
.build();
OneTimeWorkRequest MyWorkB = new OneTimeWorkRequest.Builder(MyWorkB.class)
.build();
OneTimeWorkRequest MyWorkC = new OneTimeWorkRequest.Builder(MyWorkC.class)
.build();
OneTimeWorkRequest MyWorkD = new OneTimeWorkRequest.Builder(MyWorkD.class)
.build();
OneTimeWorkRequest MyWorkE = new OneTimeWorkRequest.Builder(MyWorkE.class)
.build();
OneTimeWorkRequest MyWorkF = new OneTimeWorkRequest.Builder(MyWorkF.class)
.build();
OneTimeWorkRequest MyWorkG = new OneTimeWorkRequest.Builder(MyWorkG.class)
.build();
OneTimeWorkRequest MyWorkH = new OneTimeWorkRequest.Builder(MyWorkH.class)
.build();
OneTimeWorkRequest MyWorkI = new OneTimeWorkRequest.Builder(MyWorkI.class)
.build();
OneTimeWorkRequest MyWorkJ = new OneTimeWorkRequest.Builder(MyWorkJ.class)
.build();
OneTimeWorkRequest MyWorkK = new OneTimeWorkRequest.Builder(MyWork.class)
.build();
OneTimeWorkRequest MyWorkL = new OneTimeWorkRequest.Builder(MyWorkL.class)
.build();
List<OneTimeWorkRequest> allWorker = new ArrayList<>();
allWorker.add(MyWorkA);
allWorker.add(MyWorkB);
allWorker.add(MyWorkC);
allWorker.add(MyWorkD);
allWorker.add(MyWorkE);
allWorker.add(MyWorkF);
allWorker.add(MyWorkG);
allWorker.add(MyWorkH);
allWorker.add(MyWorkI);
allWorker.add(MyWorkJ);
WorkManager.getInstance()
.enqueue(allWorker);
和MyWorkA.java
到MyWorkJ.java
使用此代码(虚拟下载文件):
public class MyWorkA extends Worker {
private static final String TAB = MyWorkA.class.getSimpleName();
public MyWorkA(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@NonNull
@Override
public Result doWork() {
Log.e(TAB,"My WorkA");
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL("http://ipv4.download.thinkbroadband.com/20MB.zip");
connection = (HttpURLConnection) url.openConnection();
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
}
int fileLength = connection.getContentLength();
input = connection.getInputStream();
output = new FileOutputStream("/sdcard/file_nameA.zip");
byte data[] = new byte[4096];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
if (fileLength > 0)
output.write(data, 0, count);
}
} catch (Exception e) {
Log.i("test", e.getMessage());
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
return Result.success();
}
}
如果您使用的是聆听工人,则使用SetExecutor的自定义配置将无济于事。原因是该遗嘱执行人仅是为了经营工人而不是可听的工人。因此,在这种特殊情况下,您可以拥有自己的固定线程池,在开始背景过程时可以使用它们。使用固定线程池在执行人员服务中实现此目标的方法之一 -
public class MyExecutorService {
private static ExecutorService executorService = null;
public static ExecutorService getExecutorService() {
if (executorService == null) {
executorService = Executors.newFixedThreadPool(2);
}
return executorService;
}
}
public class MyListenableWorker extends ListenableWorker {
public MyListenableWorker(@NonNull Context appContext, @NonNull WorkerParameters workerParams) {
super(appContext, workerParams);
}
@NonNull
@Override
public ListenableFuture<Result> startWork() {
MyExecutorService.getExecutorService().execute(new Runnable() {
@Override
public void run() {
doBackgroundWork();
}
});
return future; // see note below
}
}
Note :如果您使用的是自定义可听工作者,则需要像此处提到的可聆听future的状态。