Introduction
When developing virtually any application with a user interface, the programmer sooner or later encounters a situation when a long-term operation is necessary. During a long-term operation, the user is usually shown a “Please Wait ...” window or something like that.
Android platform, and probably many other platforms do not allow performing long-term operations in the UI stream. When performing a long-term operation in a UI thread, you simply hang the program.
Android offers
AsyncTask solutions for this kind of tasks. AsyncTask allows you to perform long-term operation and interact with the UI stream.
')
Problem
It would seem nothing complicated, we create AsyncTask and pass the pointer to the current Activity to the created AsyncTask and everything is ready, the background process works, updates the UI, everyone is happy.
Everything works fine until the screen orientation changes (Portrait → Landscape, Landscape → Portrait), or the application is not sent to the background. Usually with this approach, after changing the orientation of the screen, the application crashes.
Why does the application crash?
Because when you change the orientation of the eran, Android recreates the Activity, as a result of the Activity to which you passed the AsyncTask link, it has already been destroyed and your AsyncTask is trying to interact with the destroyed object.
Solutions
All solve the problem in different ways, I will not describe all the proposed methods of solving, you can find them googling or in various blogs or on StackOverflow.
Each of the approaches requires the implementation of certain tweaks, additional tests, debugging, writing additional code or limiting the capabilities of the user interface.
Faced with this problem, I was very annoyed that for such a trivial task there was no ready-made boxed solution (in any case, I did not find it).
Can i try
Please do not judge strictly and do not consider self-publicity, I just want to write how I solve this problem and share the solution with others.
I wrote some semblance of the framework (I think that the framework is too loud for my solution, but due to the nature of the use, the framework is still similar) and posted it on Github.
The source codes are open, the Apache 2.0 license , I’ll emphasize once again that I don’t sell anything, do not impose or beg. The framework is called
Asmyk .
How does it work
When activating an Activity (onResume event), the Activity is marked in the context of the application. Next, the background task addresses the UI of the Activity task from the context.
Nothing complicated, however, when implementing this scheme, a novice programmer can be a bit complicated and will have to spend a couple of days to implement a quality solution.
How to implement
Download the
AAR file and
connect to the project .
If you do not extend the Application class with your implementation, specify the attribute in the application tag in the AndroidManifest.xml file:
android:name="net.mabramyan.asmyk.core.AsmykApplicationContext"
Example:
<application ... android:name="net.mabramyan.asmyk.core.AsmykApplicationContext" ... > ...
If you extend the Application class with your implementation, you must inherit your implementation from the AsmykApplicationContext class.
Activity with which you will work from the background should be inherited from AsmykCompatActivitiy.
Note: You can inherit at least all your Activity from AsmykCompatActivitiy.
Example
UI "Please wait ..."
Create an Activity inherited from AsmykPleaseWaitActivity or from AsmykBasicPleaseWaitActivity.
What you need to implement for AsmykPleaseWaitActivity
The method describes the actions that the Activity should perform when updating the status of the operation. The progressObj object will be passed from AsmykPleaseWaitTask:
void onProgress(final Object progressObj)
The method describes the actions that the Activity should perform when the operation fails. The errorObj object will be passed from AsmykPleaseWaitTask.
void onFail(final Object errorObj)
The method describes the actions that the Activity should perform if the operation is successful. The successObj object will be passed from AsmykPleaseWaitTask.
void onSuccess(final Object successObj)
What you need to implement for AsmykBasicPleaseWaitActivity
The method describes the actions that the Activity should perform if the operation is successful. The successObj object will be passed from AsmykPleaseWaitTask:
void onSuccess(final Object successObj)
The onFail and onProgress methods are already implemented. As arguments, take a String describing the error or describing the new state of the background task, respectively.
Background task
Next, create a background task by implementing the AsmykPleaseWaitTask class. You will have to implement just one method describing your background task:
void doInBackground(final AsmykApplicationContext ctx)
During the execution of the task, you can call the
void fireProgress(AsmykApplicationContext ctx, final Object progressObj)
method
void fireProgress(AsmykApplicationContext ctx, final Object progressObj)
- this method will subsequently cause onProgress to your AsmykPleaseWaitActivity. When the task is completed, call the fireSuccess or fireFailed method, depending on the result of the operation.
Launch
An example of calling a background task:
pleaseWaitTask.start((AsmykApplicationContext) MainActivity.this.getApplicationContext()); Intent intent = new Intent(MainActivity.this, PleaseWaitActivity.class); startActivity(intent);
Attention: AsmykPleaseWaitTask will actually start the task execution only after the Activity inherited from AsmykPleaseWaitActivity is displayed.
This is done so that the background task is not completed before the Activity is shown.
An example of a simple application you can see
here .
Appeal to commenting
Thanks for reading and taking the time to comment.
I am for criticism if it is constructive.
In order to make the post useful for other readers, let's do this:
If you think any code constructs are wrong, describe why.
If you offer a method that is more convenient or more correct than the one described above, apply your solution to the task (this is the main task that the above framework solves):
1) We have already received a piece of data from the user for registration, the user clicks "Continue"
2) Perform registration step 1. N different requests are sent sequentially. Here I want to show the user what the program is doing right now. At the same time, rotate the screen, etc. should not interrupt the registration process.
From my point of view, there can be many such tasks in a real application.
PS I suppose if we put real examples, the post will be as useful as possible.
That's all I wanted to say! Thanks for attention.