WorkManager原理

2022-05-30  本文已影响0人  沪漂意哥哥

基本使用

概述

WorkManager的出现,则是为应用程序中那些不需要及时完成的任务,提供统一的解决方案,以便在设备电量和用户体验之间达到一个比较好的平衡。

特点
注意

WorkManager不是一种新的工作线程,它的出现不是为了替代其它类型的工作线程。工作线程通常立即运行,并在执行完成后给到用户反馈。而WorkManager不是即时的,它不能保证任务能立即得到执行。

基础使用
dependencies {
    def versions = "2.2.0"
    implementation "androidx.work:work-runtime:$versions"
}
public class UploadLogWorker extends Worker
{
    public UploadLogWorker(@NonNull Context context, @NonNull WorkerParameters workerParams)
    {
        super(context, workerParams);
    }

    /**
     * 耗时的任务,在doWork()方法中执行
     * */
    @NonNull
    @Override
    public Result doWork()
    {
        Log.e("UploadLogWorker", "doWork()");
        return Result.success();
    }
}
Constraints constraints = new Constraints.Builder()
        .setRequiresCharging(true)
        .setRequiredNetworkType(NetworkType.CONNECTED)
        .setRequiresBatteryNotLow(true)
        .build();
OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadLogWorker.class)
        .setConstraints(constraints)//设置触发条件
        .build();
OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadLogWorker.class))
        .setBackoffCriteria(BackoffPolicy.LINEAR, OneTimeWorkRequest.MIN_BACKOFF_MILLIS, TimeUnit.MILLISECONDS)//设置指数退避算法
        .build();
WorkManager.getInstance(this).enqueue(uploadWorkRequest);
WorkManager.getInstance(this).getWorkInfoByIdLiveData(uploadWorkRequest.getId()).observe(MainActivity.this, new Observer<WorkInfo>()
{
    @Override
    public void onChanged(WorkInfo workInfo)
    {
        Log.d("onChanged()->", "workInfo:"+workInfo);
    }
});
WorkManager.getInstance(MainActivity.this).cancelAllWork();
Data inputData = new Data.Builder().putString("input_data", "Hello World!").build();

OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadLogWorker.class)
                .setInputData(inputData)
                .build();
@Override
public Result doWork()
{
    //接收外面传递进来的数据
    String inputData = getInputData().getString("input_data");

    // 任务执行完成后返回数据
    Data outputData = new Data.Builder().putString("output_data", "Task Success!").build();

    return Result.success(outputData);
}
WorkManager.getInstance(this).getWorkInfoByIdLiveData(uploadWorkRequest.getId()).observe(MainActivity.this, new Observer<WorkInfo>()
{
    @Override
    public void onChanged(WorkInfo workInfo)
    {
        if (workInfo != null && workInfo.getState() == WorkInfo.State.SUCCEEDED)
        {
            String outputData = workInfo.getOutputData().getString("output_data");
        }
    }
});

注意:Data只能用于传递一些小的基本类型数据,且数据最大不能超过10kb。

WorkManager.getInstance(this).beginWith(compressWorkRequest).then(uploadWorkRequest).enqueue();

WorkManager的任务执行

WorkManager会根据系统的版本,决定采用JobScheduler或是AlarmManager+Broadcast Receivers来完成任务。但是这些API很可能会受到OEM系统的影响。比如,假设某个系统不允许AlarmManager自动唤起,那么WorkManager很可能就无法正常使用

可能会出现失败情况

WorkManager源码分析

启动点

需要反编译Mainfast.xml文件得到具体

<?xml version="1.0" encoding="utf-8"?>
<manifest
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:versionCode="1"
 android:versionName="1.0"
 android:compileSdkVersion="30"
 android:compileSdkVersionCodename="11"
 package="com.maniu.mn_vip_jetpack_other"
 platformBuildVersionCode="30"
 platformBuildVersionName="11"
 >
 <uses-sdk
  android:minSdkVersion="21"
  android:targetSdkVersion="30"
  >
 </uses-sdk>
 <uses-permission
  android:name="android.permission.WAKE_LOCK"
  >
 </uses-permission>
 <uses-permission
  android:name="android.permission.ACCESS_NETWORK_STATE"
  >
 </uses-permission>
 <uses-permission
  android:name="android.permission.RECEIVE_BOOT_COMPLETED"
  >
 </uses-permission>
 <uses-permission
  android:name="android.permission.FOREGROUND_SERVICE"
  >
 </uses-permission>
 <application
  android:theme="@7F0D0005"
  android:label="@7F0C001B"
  android:icon="@7F0B0000"
  android:debuggable="true"
  android:testOnly="true"
  android:allowBackup="true"
  android:supportsRtl="true"
  android:roundIcon="@7F0B0001"
  android:appComponentFactory="androidx.core.app.CoreComponentFactory"
  >
  <activity
   android:name="com.maniu.mn_vip_jetpack_other.MainActivity"
   >
   <intent-filter
    >
    <action
     android:name="android.intent.action.MAIN"
     >
    </action>
    <category
     android:name="android.intent.category.LAUNCHER"
     >
    </category>
   </intent-filter>
  </activity>
  <activity
   android:name="com.maniu.mn_vip_jetpack_other.paging.PagingActivity"
   >
  </activity>
  <provider
   android:name="androidx.work.impl.WorkManagerInitializer"
   android:exported="false"
   android:multiprocess="true"
   android:authorities="com.maniu.mn_vip_jetpack_other.workmanager-init"
   android:directBootAware="false"
   >
  </provider>
  <service
   android:name="androidx.work.impl.background.systemalarm.SystemAlarmService"
   android:enabled="@7F030003"
   android:exported="false"
   android:directBootAware="false"
   >
  </service>
  <service
   android:name="androidx.work.impl.background.systemjob.SystemJobService"
   android:permission="android.permission.BIND_JOB_SERVICE"
   android:enabled="@7F030005"
   android:exported="true"
   android:directBootAware="false"
   >
  </service>
  <service
   android:name="androidx.work.impl.foreground.SystemForegroundService"
   android:enabled="@7F030004"
   android:exported="false"
   android:directBootAware="false"
   >
  </service>
  <receiver
   android:name="androidx.work.impl.utils.ForceStopRunnable$BroadcastReceiver"
   android:enabled="true"
   android:exported="false"
   android:directBootAware="false"
   >
  </receiver>
  <receiver
   android:name="androidx.work.impl.background.systemalarm.ConstraintProxy$BatteryChargingProxy"
   android:enabled="false"
   android:exported="false"
   android:directBootAware="false"
   >
   <intent-filter
    >
    <action
     android:name="android.intent.action.ACTION_POWER_CONNECTED"
     >
    </action>
    <action
     android:name="android.intent.action.ACTION_POWER_DISCONNECTED"
     >
    </action>
   </intent-filter>
  </receiver>
  <receiver
   android:name="androidx.work.impl.background.systemalarm.ConstraintProxy$BatteryNotLowProxy"
   android:enabled="false"
   android:exported="false"
   android:directBootAware="false"
   >
   <intent-filter
    >
    <action
     android:name="android.intent.action.BATTERY_OKAY"
     >
    </action>
    <action
     android:name="android.intent.action.BATTERY_LOW"
     >
    </action>
   </intent-filter>
  </receiver>
  <receiver
   android:name="androidx.work.impl.background.systemalarm.ConstraintProxy$StorageNotLowProxy"
   android:enabled="false"
   android:exported="false"
   android:directBootAware="false"
   >
   <intent-filter
    >
    <action
     android:name="android.intent.action.DEVICE_STORAGE_LOW"
     >
    </action>
    <action
     android:name="android.intent.action.DEVICE_STORAGE_OK"
     >
    </action>
   </intent-filter>
  </receiver>
  <receiver
   android:name="androidx.work.impl.background.systemalarm.ConstraintProxy$NetworkStateProxy"
   android:enabled="false"
   android:exported="false"
   android:directBootAware="false"
   >
   <intent-filter
    >
    <action
     android:name="android.net.conn.CONNECTIVITY_CHANGE"
     >
    </action>
   </intent-filter>
  </receiver>
  <receiver
   android:name="androidx.work.impl.background.systemalarm.RescheduleReceiver"
   android:enabled="false"
   android:exported="false"
   android:directBootAware="false"
   >
   <intent-filter
    >
    <action
     android:name="android.intent.action.BOOT_COMPLETED"
     >
    </action>
    <action
     android:name="android.intent.action.TIME_SET"
     >
    </action>
    <action
     android:name="android.intent.action.TIMEZONE_CHANGED"
     >
    </action>
   </intent-filter>
  </receiver>
  <receiver
   android:name="androidx.work.impl.background.systemalarm.ConstraintProxyUpdateReceiver"
   android:enabled="@7F030003"
   android:exported="false"
   android:directBootAware="false"
   >
   <intent-filter
    >
    <action
     android:name="androidx.work.impl.background.systemalarm.UpdateProxies"
     >
    </action>
   </intent-filter>
  </receiver>
  <service
   android:name="androidx.room.MultiInstanceInvalidationService"
   android:exported="false"
   >
  </service>
  <provider
   android:name="androidx.lifecycle.ProcessLifecycleOwnerInitializer"
   android:exported="false"
   android:multiprocess="true"
   android:authorities="com.maniu.mn_vip_jetpack_other.lifecycle-process"
   >
  </provider>
 </application>
</manifest>
创建过程的调用
public static @NonNull WorkManager getInstance(@NonNull Context context) {
        return WorkManagerImpl.getInstance(context);
    }
public static @NonNull WorkManagerImpl getInstance(@NonNull Context context) {
        synchronized (sLock) {
            WorkManagerImpl instance = getInstance();
            if (instance == null) {
               ...
                } else {
                    throw new IllegalStateException("WorkManager is not initialized properly.  You "
                            + "have explicitly disabled WorkManagerInitializer in your manifest, "
                            + "have not manually called WorkManager#initialize at this point, and "
                            + "your Application does not implement Configuration.Provider.");
                }
            }

            return instance;
        }
    }

    public static @Nullable WorkManagerImpl getInstance() {
        synchronized (sLock) {
            if (sDelegatedInstance != null) {
                return sDelegatedInstance;
            }

            return sDefaultInstance;
        }
    }
WorkManagerImpl目的

找到真正执行任务的人

image.png
任务如何加入到队列的enqueue方法
scheduleWorkInBackground
GreedyScheduler怎么执行
image.png
image.png
image.png
上一篇下一篇

猜你喜欢

热点阅读