Android WorkManager同时启动太多工作

时间:2019-02-21 19:00:16

标签: android android-workmanager

我正在使用workmanager在我的应用程序中实现并行后台上传/下载功能。一切正常,但WorkManager会同时运行太多工作,并且电话会变得无响应,直到处理完成。我想排队说10个任务,并让WM并行执行说2个任务,直到完成所有10个任务。 WorkManager似乎并行执行5-10。我不知道该怎么做。我只用一个线程执行器尝试了自己的配置,并且没有任何区别。如何限制一次执行的作业数量?我正在使用1.0.0-rc01。

3 个答案:

答案 0 :(得分:1)

您可以使用自定义Configuration来定义要同时执行的Worker个数量。 Application.onCreate()中有类似的内容。有关更多信息,请参见如何使用自定义配置初始化WorkManager

val config = Configuration.Builder()
  .setExecutor(yourExecutor)
  .build()

WorkManager.initialize(context, config)

答案 1 :(得分:0)

如果您使用的是ListenableWorker,那么将ConfigurationsetExecutor一起使用将无济于事。原因是这个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.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();
    }
}