我正在使用workmanager在我的应用程序中实现并行后台上传/下载功能。一切正常,但WorkManager会同时运行太多工作,并且电话会变得无响应,直到处理完成。我想排队说10个任务,并让WM并行执行说2个任务,直到完成所有10个任务。 WorkManager似乎并行执行5-10。我不知道该怎么做。我只用一个线程执行器尝试了自己的配置,并且没有任何区别。如何限制一次执行的作业数量?我正在使用1.0.0-rc01。
答案 0 :(得分:1)
您可以使用自定义Configuration
来定义要同时执行的Worker
个数量。 Application.onCreate()
中有类似的内容。有关更多信息,请参见如何使用自定义配置初始化WorkManager
。
val config = Configuration.Builder()
.setExecutor(yourExecutor)
.build()
WorkManager.initialize(context, config)
答案 1 :(得分:0)
如果您使用的是ListenableWorker,那么将Configuration与setExecutor一起使用将无济于事。原因是这个executor仅用于运行Worker而不是ListenableWorker。因此,在这种特定情况下,您可以拥有自己的固定线程池,您可以在starting the background process期间使用它。在ExecutorService-
中使用固定线程池实现此目标的方法之一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
}
}
注意:如果您使用的是自定义的ListenableWorker,则需要保持here之类的ListenableFuture状态。
答案 2 :(得分:0)
我测试了此示例代码并为我工作,没有任何错误,没有任何延迟和冻结UI线程的10个并行执行节点(.setExecutor(Executors.newFixedThreadPool(10))
)用于下载文件:
我使用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();
}
}