Android Oreo-Job Intent Service在主线程上运行,导致应用冻结了几秒钟

时间:2018-11-09 01:50:25

标签: android android-jobscheduler

我正在尝试在后台下载一些文件。之前我在使用Intent服务,而我的应用程序不会因为使用Intent服务而冻结。但是,与oreo及更高版本一样,只要应用程序从后台关闭,Intent服务就会被销毁。我在Job服务中执行了相同的处理,但是它似乎在主线程上运行。对于不应该在主线程上运行的后台处理,我该怎么办?

下面是我执行的Job调度代码:

public class Util {

    // schedule the start of the service every 10 - 30 seconds
    @TargetApi(Build.VERSION_CODES.M)
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public static void scheduleJob(Context context) {
        ComponentName serviceComponent = new ComponentName(context, MyService.class);
        JobInfo.Builder builder = new JobInfo.Builder(0, serviceComponent);
        builder.setMinimumLatency(1 * 1000); // wait at least
        builder.setOverrideDeadline(3 * 1000); // maximum delay
        //builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); // require unmetered network
        //builder.setRequiresDeviceIdle(true); // device should be idle
        //builder.setRequiresCharging(false); // we don't care if the device is charging or not
        JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
        jobScheduler.schedule(builder.build());
    }

}



@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class MyService extends JobService {
    private static final String TAG = "SyncService";
    public Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
    public SharedPreferences sharedPreferences;
    public ComplexObject complexObject;
    private Context context;
    public static final String NOTIFICATION_CHANNEL_ID = "10001";
    @Override
    public boolean onStartJob(JobParameters params) {
        System.out.println("RUnning this Job.......");
        context = this;
        this.sharedPreferences = context.getSharedPreferences(context.getResources().getString(R.string.shared_preference_key), Context.MODE_PRIVATE);

        //30-40 HTTP call to process the data
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        return true;
    }

3 个答案:

答案 0 :(得分:1)

根据文档:

  

此服务在应用程序主线程上运行的Handler上执行每个传入的作业。这意味着您必须将执行逻辑卸载到您选择的另一个线程/处理程序/ AsyncTask。否则将导致阻止JobManager将来进行任何回调,特别是onStopJob(android.app.job.JobParameters),这是为了通知您不再满足计划要求。

因此,您将需要使用AsyncTask或某种其他形式的异步方法来执行逻辑。不过,您应该使用可取消的内容,因为调用onStopJob()时,您应该停止正在执行的操作。

还记得在逻辑完成后调用jobFinished()

答案 1 :(得分:1)

因为它有点旧,所以不确定是否对您有帮助,但是:
您的标题为JobIntentService,使用JobService,答案为 TheWanderer引用您使用的类(JobService),但是如果您将使用JobIntentService,则其方法onHandleWork在后台线程上运行:

  

在后台线程上调用此方法,因此您可以在此处执行长时间的阻塞操作。

答案 2 :(得分:0)

您可以将JobIntentService用作下载/上传某些文件甚至与服务器通信的解决方案。另一个更好甚至更好的方法是WorkManager。请注意,IntentService在UI线程上运行,而onHandleIntent(Intent intent)在UI线程上运行。因此,我们应该使用单独的线程或使用例如AsyncTask。但是JobIntentService具有功能onHandleWork(@NonNull Intent intent),该功能在后台线程上运行,因此我们只在其上进行工作。在WorkManager方法中,工作是通过Worker的doWork()方法完成的,并且此函数也在后台线程上运行,因此我们应在其中编写主要代码。我认为JobIntentService和WorkerManager都适合于此目的。 JobIntentService只需运行一次工作,但是通过WorkManager,我们可以一次完成工作或定期重复工作(每个周期之间的间隔时间至少为15分钟)。