【问题标题】:Using Main Thread to Trigger a Firebase JobDispatcher into BG Thread使用主线程触发 Firebase JobDispatcher 进入 BG 线程
【发布时间】:2017-09-11 17:47:41
【问题描述】:

我目前正在使用 Firebase JobDispatcher 使用服务意图在后台运行定期检查(在启动、安装和更新时注册)。这工作正常,它产生了与主线程分开的自己的线程,所以我没有锁定 UI,它正确地终止了线程,所以垃圾收集不会成为问题。

我还想从应用内的主线程触发同样的工作。问题是运行 jobdispatcher onCreate 会触发作业在主 UI 线程中运行,而不是在后台线程中运行。我的一个函数可以生成很多对象,所以即使它正常运行,它也会破坏应用程序的可用性,因为 GC 永远无法摆脱所有垃圾。

如何从主线程按需运行现有的 JobDispatcher 作业,但仍然在单独的线程中?

非常感谢您的帮助。

为澄清此特定用途而进行的编辑

我的特殊情况涉及第一次运行,其中 UpdateNetworkerJob.class 可能需要几分钟才能运行。 phoneHistoryCheck.GetLastCallChecked() 函数有一个循环,可以多次调用 Firebase,检索和放置信息。

9/12 更新

后续运行非常快,AsyncTask 可以工作。但是我发现我需要一个更强大的解决方案,目前正在查看ThreadPoolExecutor。有可能 GetLastCallChecked() 函数在 Firebase 引擎上抛出了太多东西,并导致主线程对 Firebase 的调用在赶上的噪音中下降。我正在整理这部分。

在主线程中开始工作的代码:

FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(trackedContactListActivity.this));
        Job myJob = dispatcher.newJobBuilder()
                .setService(UpdateNetworkerJob.class)
                .setTag("UpdateNetworkerService")
                .setTrigger(Trigger.NOW)
                .setConstraints(
                        Constraint.ON_ANY_NETWORK
                )
                .build();

        dispatcher.mustSchedule(myJob);

UpdateNetworkerJob.class

public class UpdateNetworkerJob extends JobService {

private static final String TAG = "UpdateNetworkerJob";

@Override
public boolean onStartJob(final JobParameters params) {


    Log.d(TAG, "UpdateNetworkerJob is running with params: " + params);
    PhoneHistoryCheck phoneHistoryCheck = new PhoneHistoryCheck();
    phoneHistoryCheck.GetLastCallChecked(UpdateNetworkerJob.this);



    return false;
}

@Override
public boolean onStopJob(JobParameters params) {
    // Stop tracking these job parameters, as we've 'finished' executing.
    //sendMessage(MSG_COLOR_STOP, params.getJobId());
    Log.d(TAG, "on stop job: " + params);

    // Return false to drop the job.
    return false;
}
}

【问题讨论】:

  • 你的帖子说:这工作正常,它产生了它自己的线程。那是指UpdateNetworkerJob吗?我看不到它在哪里创建工作线程。您还声明:问题是运行 jobdispatcher onCreate 会触发作业在主 UI 线程中运行,而不是在后台线程中运行。调度的作业是JobService,它在主线程上运行,不管调度它的线程是什么。您必须创建自己的 JobService 工作线程。见:intro to the JobService docs
  • 正确。我的扩展广播接收器的类不包含在原始问题中。我运行了一个类似的 FirebaseJobDispatcher,但它在清单中的意图下注册:BOOT_COMPLETED、PACKAGE_REPLACED、PACKAGE_ADDED。以这种方式运行时,我可以看到我的应用程序的一个单独线程在 Android 监视器中生成并终止。您指出的那些文档提到需要卸载工作的“线程/处理程序/AsyncTask”。你是这个意思吗?所以这遵循下面的逻辑——我需要以某种方式手动启动一个单独的线程。感谢您的帮助。
  • 您可以使用Thread.currentThread().getName() 获取线程名称。将其添加到来自UpdateNetworkerJob 的一些日志输出中。我非常有信心它将成为主/ UI 线程,即使是从您的 BroadcastReceiver 启动的。是的,您需要返工 UpdateNetworkerJob 以在工作线程或 AsyncTask 中执行长时间处理。
  • 啊...好的。会检查的。因此,仅在 Android Monitor 中看到第二个线程 ID 并不能保证它实际上是独立的?抱歉,我显然对此很陌生。非常感谢您的帮助!
  • 我不知道第二个线程是什么。很确定这不是你的 JobService。

标签: android multithreading firebase firebase-job-dispatcher


【解决方案1】:

AsyncTask 里面的东西可以运行多长时间没有限制吗?第一次在我的应用程序中运行它们可以运行几分钟。

您可以在Threading performance 文章中找到问题的答案。

使用 AsyncTask 时,需要牢记几个重要的性能方面。

首先,默认情况下,应用会将其创建的所有 AsyncTask 对象推送到单个线程中。因此,它们以串行方式执行,并且与主线程一样,特别长的工作包会阻塞队列。 因此,我们建议您只使用 AsyncTask 来处理持续时间短于 5 毫秒的工作项

HandlerThreadThreadPoolExecutor 提供了其他选择。

您可以在这篇文章中找到HandlerThread 的示例代码:

Call Main thread from secondary thread in Android

【讨论】:

  • 这很有意义。我想我已经成功地为我的函数实现了 AsyncTask,而且速度要快得多,但是当第一次运行发生时,我仍然会收到 ANR 弹出窗口。我还不能确定是因为我淹没了 Firebase 引擎的队列,还是因为其他原因。我会尝试这个实现,看看它是否能解决我的问题。
  • 如果您的应用程序有一个耗时的初始设置阶段,请考虑尽快显示启动屏幕或渲染主视图,指示正在加载并异步填充信息。无论哪种情况,您都应该以某种方式表明正在取得进展,以免用户认为应用程序已冻结。 (来自developer.android.com/training/articles/perf-anr.html
  • 这是一个非常好的观点。当我一起破解 MVP 时,我已经降低了入职活动的优先级。现在可能是开始这样做的好时机。我仍然需要解决这个问题,但这将有助于妥善组织它,而不是固定在我的主要活动上。
  • 如果可能,尝试将初始化期间长时间运行的任务拆分为多个短任务。
【解决方案2】:

请从AsynctaskdoinBackground 函数调用您的服务意图。示例在这里:Asynctask documentation

您可以通过 UI 控制 Asynctask,而无需按住 UI 来查看结果。

【讨论】:

  • 所以这不是使用 JobDispatcher 吗?在那种情况下,我只需将我从 UpdateNetworkerJob.class 触发的函数放入 AsyncTask 中,对吗?
  • 还有一个后续问题:AsyncTask 里面的东西可以运行多长时间没有限制吗?第一次在我的应用程序中运行时,它们可以运行几分钟。
  • @VinceAnido - 是的,从技术上讲,您可以从 JobDispatcher 获取函数并将它们直接插入 Asynctask。 AsyncTask 可以运行几分钟,因为它在后台运行并且即使主要活动被破坏也会继续。但是为了防止多个AsyncTasks同时运行,你应该在Asynctask的“onPreexecute”函数中做一些检查,以确保只有1个任务在运行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-12
  • 1970-01-01
  • 2013-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多