Android Workmanager同时启动了太多工作



我正在使用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.javaMyWorkJ.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的状态。

最新更新