how to avoid activity closing before the thread in fragment completed - android-fragments

Im having activity A.Inside that im having Fragment Fa.
In Fa im having button Bu.
When users clicks the Bu then it will start the thread.The status of progress of thread and after completing the result is shown in the activity via handler.
But when user clicks the button the thread starts and b4 completion of thread when user clicks back button means then activity/fragment closed then handler become null.
But thread runs and after completing throws null pointer for handler.
I need if user clicks back button means how to make fragment/activity will wait till thread need to complete?
The following are my configuration details
Android minimum sdk version = 4.4

Related

OnNavigatedTo vs Initialize(Async)

I am having a hard time to understand when to use Initialize and when to use OnNavigatedTo.
I understand that Initialize is execute once when the view model is initialized and OnNavigatedTo is executed every time I navigate to the page.
What is the best way on deciding what to do in Initialize and what to do in OnNavigatedTo?
Especially in a situation where I have data passed by navigation parameters but also fetched from additional apis (some even with http calls that can take a while)
Thanks a lot
Using Initialize will be triggered only when your ViewModel is created meaning you will have to destroy it and recreated it before triggering this method again.
OnNavigatedTo will be triggered every time your page (the one linked to this ViewModel) will appears, meaning it will be the case on the first navigation (same as Initialized) but also every time you will go back to this page.
So if you have the following navigation pattern: Page 1 > Page 2 > Go back to Page 1, Initialized will be triggered only on step 1 (creation of your ViewModel) while OnNavigatedTo will be triggered twice, once in step 1 and the other time on step 3.

flutter and bloc asynchronous yield

I am using flutter with the BLoC pattern (with the flutter_bloc library) and I have these events:
PersonalFileAddedEvent(File file), PersonalFileUploadEvent(PersonalFile file) (both extend from PersonalFileEvent)
File is a file from the file picker, PersonalFile is a class that has these enum statuses: READY_TO_UPLOAD, UPLOADING, UPLOAD_FINISHED.
And this status from the BLoC:
PersonalFileListLoadedState(List<PersonalFile> files) (extend from PersonalFileListState)
When the user selects a file, the UI calls the event PersonalFileAddedEvent and passes it to the BLoC which creates a PersonalFile object and sets it's status to READY_TO_UPLOAD. This PersonalFile object gets
added to a list which holds all the PersonalFile's that the user is adding (and uploading). The BLoC then responds (yield) with the PersonalFileListLoadedState(blocPersonalFileList) to the UI to render the information.
Once added, an "upload now" button gets rendered in the UI for that PersonalFile. When pressed, this calls the PersonalFileUploadEvent event and sends along the PersonalFile to the BLoC to start the upload process (multipart upload).
Immediately after receiving the event, the BLoC updates this PersonalFile's status to UPLOADING and yield the PersonalFileListLoadedState state with the PersonalFile's status updated for the UI to show that it is uploading.
The method that uploads the multipart file is async:
Future<PersonalFile> upload(PersonalFile file) async { //upload code }
This is the mapEventToState from flutter_bloc:
Stream<PersonalFileListState> mapEventToState(PersonalFileEvent event) async* {}
Inside this mapEventToState method I am awaiting the upload method to update the PersonalFile's status to UPLOAD_FINISHED.
The problem starts now, as the user adds several files from the file picker, and presses all the "upload" buttons. The BLoC gets blocked after receiving the first event and processes the events "synchronous like" and the UI
remains as if the other's PersonalFile's "upload" button were not pressed until the first one finishes (then the next one, and so on).
After one event gets fully processed (the upload completes), the next one gets processed, which makes sense since I am awaiting for the upload method to finish.
How can I write this code so that if the user presses several "upload" buttons in the UI, the BLoC does not get blocked (and thus the UI because the BLoC is unable to yield the new state) and all the files get uploaded
in parallel but only until each one finishes the BLoC sends the new List of PersonalFile with their status changed to UPLOAD_FINISHED?
I have tried changing the upload method's signature to:
Stream<PersonalFile> upload(PersonalFile file) async* { //upload code }
and using:
.then((file) { yield PersonalFileListLoadedState(listWithUpdatedPersonalFileStatus) })
but the code inside never gets executed. I tried debug but I cannot reach the breakpoint.
Not sure how are you calling the bloc to start the process upload.
But if you are using bloc.add(event) when the button is pressed it should be processed in an asyncronous way and yield the new statuses as needed.
Also notice that when you are processing the status change if the same state is yielded several times, the listener will listen to it only once so you wont see more than one update in your UI.
Hope this helps.

when the event loop starts in Dart and how the event queue works

The first question is when the event loop starts ?
I read in a site that it's start after the main method
but why when we try something like this
main()async {
Future(()=>print('future1'));
await Future(()=>print('future2'));
print('end of main');
}
//the output is :
//future1
//future2
//end of main
in this example the event loop start when we use the await keyword and
after the event loop reaches the future2 it's paused ?
or i am wrong :(
The second question is how the events is added to event queue
if it's FIFO why in this example the future 2 is completed before
future 1
main(){
Future.delayed(Duration(seconds:5) , ()=>print('future1'));
Future.delayed(Duration(seconds:2) , ()=>print('future2'));
}
The event loop run when there is nothing else running (e.g. main method is done, you are waiting for some future to complete).
Your example makes sense because the first line puts an event on event queue so now the first item in the queue is "print('future1')". In the next line, you are putting another event on the queue which calls "print('future2')" and now you await for this event to be done.
Since your main method is not waiting for something then the event loop is going to be executed. Since the first event on the queue was "print('future1')" then this is going to be executed first. But since the main method is still waiting for the future "print('future2')" to be complete then the event loop takes another event to be executed which are going to be "print('future2')".
Since this event was the one the main method was waiting for (and there is no more event on the event queue) then main() are going to run the last call "print('end of main')".
In your next example, you think that Future and Future.delayed are the same which it is not. With Future.delayed there are not going any event in the event queue before. Instead, there are running a thread outside the VM which knows when the next timer should trigger which ends up putting an event on the queue. So the event is only being put on the event queue when the timer has been expired (and therefore, the future2 are going to be executed first).

Check an event is processed or not after QCoreApplication::postEvent

I make user-event and send it an object in another thread using postEvent(). Since the receiver can be destroyed before it process the event, I want to know the event is processed or not. But QML doc says
It is not safe to access the event after it has been posted.
Is there a way to know the event is processed or not?

Toast from destroyed activity/fragment, getString issue

I have a fragment with UI that is responsible for doing short async api-calls. When an async task completes fragment triggers a Toast message with a result-string.
My issue is that if a user presses Back button without waiting for the result the app crushes due to a onPostExecute method, which in turn triggers Toast + getString(R.string.whatever) in the fragment that is already detached, because the activity is behind the onDestroy state.
I can check whether the fragment is detached or use a ProgressDialog, which is modal but I think it would be nice to show the toasts without blocking or any other quirks. Any suggestions on how to achieve it? Broadcast receiver in the application class == overkill?
Thanks.
UPD logs:
01-24 12:01:29.626: E/AndroidRuntime(616):
java.lang.IllegalStateException: Fragment
HandsetSocialNetworksFragment{40612a78} not attached to Activity 01-24
12:01:29.626: E/AndroidRuntime(616): at
android.support.v4.app.Fragment.getResources(Fragment.java:571) 01-24
12:01:29.626: E/AndroidRuntime(616): at
android.support.v4.app.Fragment.getString(Fragment.java:593)
At the start of the async call, get the activity from the fragment, and get the application context from it. Use that one later to get the string you need.
Alternatively, you can fetch the string you need when you start the async call, instead of when you have to show the toast.

Resources