Reputation: 87
I have an application on an android tablet that sends a log file back to me after the user does certain things. I have had it setup already, being able to send the log file that I am creating in an AsyncTask. As the log file gets bigger and bigger it takes longer to send, and I am starting to run into an issue where it starts sending another log file before the first one finishes.
The code is simply
private class SendLogFile extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
//Send Log File From Tablet to Server
}
}
being called with a simple
new SendLogFile().execute();
Is there a way for me to not run a new SendLogFile AsyncTask if there is one currently executing? I do NOT want to set it up as a recurring task with a timer, I still want it started off user actions.
Thanks.
Upvotes: 0
Views: 104
Reputation: 6008
I suggested to use RxJava if it is possible, since the logic flow is more advanced and complicated in the future. And more separate thread is needed for the job. I think you should include some logic in Fragment/Activity for you work (They are in the zone between View and controller in MVC Pattern)
From Gabe Sechan's response, it would be great if you can just send the diff to the server. If it is not possible, you can to save the current checksum of the file in your device. At least it can save you the time to upload if there is no change in the log.
Tutorial is here for replacing asynctask. http://blog.stablekernel.com/replace-asynctask-asynctaskloader-rx-observable-rxjava-android-patterns/
Upvotes: 0
Reputation: 368
There is a simple solution for this problem, use Intent services. You can execute as many as you want and it will automatically create a qeue and execute it one after another until there are no commands left, that will solve your problem, use this class that i created.
public class FeedBackSyncCommand extends IntentService {
public static final String ARG_LOG_FILE = "Log";
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public FeedBackSyncCommand(String name) {
super(name);
}
@Override
protected void onHandleIntent(Intent intent) {
String logFile = intent != null ?
intent.getStringExtra(ARG_LOG_FILE) :
"Log not available";
// do stuff with your log file
}
}
And you can use it this way (starting 10 instances of the service):
Intent feedBackCommand =
new Intent(getApplicationContext(), FeedBackSyncCommand.class);
for (int i = 0; i < 11; i ++) {
feedBackCommand.removeExtra(FeedBackSyncCommand.ARG_LOG_FILE);
feedBackCommand.putExtra(FeedBackSyncCommand.ARG_LOG_FILE,
"This is an example log file" + 1);
getApplicationContext().startService(feedBackCommand);
}
Upvotes: 0
Reputation: 11028
Call newSingleThreadExecutor()
and run your AsyncTask
on the returned executor:
https://developer.android.com/reference/java/util/concurrent/Executors.html#newSingleThreadExecutor()
Upvotes: 0
Reputation: 7862
You can use a ThreadPoolExecutor with a size of 1, and just submit tasks to it. It will only execute one after the other.
Upvotes: 0
Reputation: 93542
You realize that you're creating a bottleneck here, right? If you have trouble as the log file gets bigger, your approach is wrong. Don't send up the whole log, send up the diffs.
Ignoring that- I wouldn't use an AsyncTask. I'd use a Thread. The Thread sits around and waits for a send log message. When it gets one it sends it. Since its the only thread sending logs it can never be sending two at once.
Upvotes: 2