Using Main Thread to Trigger a Firebase JobDispatcher into BG Thread

664 views Asked by At

I'm currently using Firebase JobDispatcher to run a periodic check in the background using the service intent (registered on boot, install & update). This is working correctly, and it spawns it's own thread separate from the main thread, so I don't lock the UI, and it kills the thread properly so garbage collection doesn't become a problem.

I would also like to trigger this same exact work from the main thread in-app. The problem is that running a jobdispatcher onCreate triggers the job to run in the main UI thread, and not in a background thread. One of my functions can generate A LOT of objects, so even though it properly runs, it kills usability in the app because the GC never can get rid of all the junk.

How can I run an existing JobDispatcher job on demand from the main thread, but still in a separate thread?

Thanks so much for your help.

Edits for clarification of this specific usage

My particular case involves a first run, where UpdateNetworkerJob.class can take several minutes to run. The phoneHistoryCheck.GetLastCallChecked() function has a loop which makes several calls to Firebase, both retrieving and putting information.

9/12 Update

Subsequent runs are very quick, and AsyncTask can work. However I am finding I need a more robust solution and am currently looking at ThreadPoolExecutor. It's possible that the GetLastCallChecked() function is throwing too much at the Firebase Engine and it causing the main thread's calls to Firebase to be way down in the noise as it catches up. I'm working on sorting this part out.

Code in main thread to start the work:

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;
}
}
2

There are 2 answers

4
Ravindra babu On

Doesn't AsyncTask have limitations on how long things inside it can run? The first time these run in my application they can run for several minutes.

You can find answers to your queries in Threading performance article.

When using AsyncTask, there are a few important performance aspects to keep in mind.

First, by default, an app pushes all of the AsyncTask objects it creates into a single thread. Therefore, they execute in serial fashion, and—as with the main thread—an especially long work packet can block the queue. For this reason, we suggest that you only use AsyncTask to handle work items shorter than 5ms in duration

HandlerThread and ThreadPoolExecutor provides other alternatives.

You can find example code of HandlerThread in this post:

Call Main thread from secondary thread in Android

3
Abhishek On

Please call your service intent from the doinBackground function of an Asynctask. Example is here : Asynctask documentation

you can control the Asynctask from your UI without holding the UI for results.