Updating multiple instances of the same dialog fragment - android

I have an app where multiple emergency messages can be received. When each message is received it needs to open a dialog with the emergency details. If more than one emergency is received it will stack the dialogs so that when the most recent emergency message is dealt with and that particular dialog closes, the previous most recent and un-handled emergency should appear, as if they are stacked.
Also, the details for each emergency are updated every x seconds from a service and these changes need to make their way to the correct dialog instance so that, when on screen the dialog is up to date.
I had this working in, I think, an un-efficient way. I was storing the instance of each dialog fragment object in a list and updating that instance with new details and then opening it. This meant that if 50 emergencies were spammed I was storing 50 dialogs. Not great for memory.
Also, this method didn't work well with orientation, where the object is destroyed and re-built, it was taken out of my list and the details reverted to the original details which were stored in it's intent.
I am looking for a way to do this that is as efficient as possible and I wanted to ask your collective Android brain for suggestions.
How would I efficiently manage multiple instances of the same dialog class to get the behaviour I require?

What i would do, is to just hold EmergencyMessage data object stack in my Activity. When stack is not empty, i would show new DialogFragment, and pass it EmergencyMessage from top of the stack, using Fragment.setArguments.
In my DialogFragment, i would use Fragment.getArguments to get EmergencyMessage object and display message. When user deals with message, notify your activity (for example like this) and close dialog. Then, if you still have unhandled EmergencyMessages in your stack, just repeat the process.
This way you always have single DialogFragment instance active at any given time.
Now, regarding updating the EmergencyMessage contents if DialogFragment is already showing this message, you can do it from activity like this:
When you create dialog, pass it tag "EmergencyMessageDialog" so you can retreive dialog later and interact with it.
MyDialogFragment dialog = (MyDialogFragment)
getFragmentManager().findFragmentByTag("EmergencyMessageDialog");
dialog.updateEmergencyMessage(newEmergencyMessage);
If you receive update for EmergencyMessage that hasnt been shown yet, you can just update your EmergencyMessage object in your stack in activity, so that would be easy.

Related

Android ViewModel: How to get a result from the Activity (best practice)?

I have the following situation:
The user opens a dialog in which the user enters information
The user closes the dialog and returns to the default UI
The data is send to the backend
Now I wonder how to implement this in a good way. At first, I think the Activity calls a method in the ViewModel to trigger an event. Secondly, the ViewModel updates an LiveData-object to trigger an observer in the Activity which opens the dialog. But after that I don't know how to implement the rest in a "best practice"-way. My current implementation is that, when the user closes the dialog, the Activity calls a "finish"-method in the ViewModel and hands over the data from the dialog as arguments. After that the ViewModel updates the LiveData-object and the event is over.
You don't specifically need to have a flow Activity -> ViewModel -> Activity, when you're just about opening a dialog. It would make sense if you have to get some info (for example price) from your back-end side and include it into your dialog description. If it's just a simple UI stuff like "show-me-a-dialog", then it's fine to leave it on your UI layer only.
And when the dialog is closed, you'll just pass needed arguments to VM, make your back-end request, and in this case it's logical to emit some event to your Live Data and it's a common practice.
Android has a bunch of really great articles and they were added no so long ago, take a look here (picture was also taken from the article). They have clear and simple explanation about all UI-VM-Data/Domain communication and how to do that it in the "right way".

Launching dialog activity from services caused 'MainActivity' to also launch

I am designing an app that is used for emergency alerts. The alerts come from a server and a connection to that server is maintained in service.
If the service receives an emergency request from the server it checks to see if a specific activity is open. If it is it lets it know an emergency has been triggered and the activity launches a dialog activity with some options. It then handles results from this new dialog activity.
However, if the service notes that the activity is NOT open I want it to launch the dialog anyway. I know that this isn't good practise but because of the importance of this emergency I don't want to rely on Notifications (which are already in use if the activity is closed to let the user know that the app is still listening for emergencies).
What currently happens is that the below code is executed in the service and the dialog launches. However, the 'main' activity (the only other activity in the app) also opens behind the dialog. What I really want to happen is that either...
1) The service launches the main activity which then opens the dialog so that I can easily capture the results.
2) The service launches only the dialog activity and I use a broadcast receiver to capture results from this activity.
1 would use the mechanics that already exist for capturing results from an activity. However I don't like the idea of chaining the activities together in this way.
2 means I can ignore the main activity all together (because I don't really need it in this instance) but seems more of a get around.
What I am really asking is two things. What is best practise given my circumstances and how do i achieve number 2? Here is the launch code in my service. Notification in this code is referring to the dialog activity that will open.
if (MainActivity.isActivityInUI) {
//Dealt with by activity
sendMessageAlert(message);
} else {
//Launch dialog directly from service
Intent notification = new Intent(this,
EmergencyNotificationActivity.class);
Bundle args = new Bundle();
args.putString(MobileMessage.EXTRA_LOCATION_NAME,
message.locationName);
args.putString(MobileMessage.EXTRA_ID,
String.valueOf(message.id));
args.putDouble(MobileMessage.EXTRA_LATITUDE,
Double.valueOf(message.latitude));
args.putDouble(MobileMessage.EXTRA_LONGITUDE,
Double.valueOf(message.longitude));
//and the flag to let the notification know this is from a service...
args.putBoolean(EXTRA_FROM_SERVICE, true);
notification.putExtras(args);
//add flag because this is being called from outside of an activity
notification.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |ActivityInfo.LAUNCH_SINGLE_INSTANCE);
startActivity(notification);
I think instead of trying to show a dialog without visibly showing an Activity, you should consider launching an Activity that is themed like a Dialog. Just apply the following theme: http://developer.android.com/reference/android/R.style.html#Theme_Dialog (or similar themes) to your EmergencyNotificationActivity. You probably would have to tweak your class to behave like a dialog instead of launching one (which I am assuming is what you're doing currently).
This method would also allow you to not have to check if an Activity already exists.

Loading Dialog while rotating device

I have an activity with in which there is a async task that will do some download stuff. AT the time of downlaoding it will show a loading dialog.
My problem is, it worked fine for me when me doing it in only one orentiaon. But when i rotate at the time of download, it shows window leaked and will crash at the
dialog.cancel in my post excute.
From my study on it more i understood it due the change in the context when device is rotated.
That is when a device is rotated the activity will be recreated so the context will be changed.
But i have created the dialog with old one and that wasn't the current context. So when i cancel it it shows error
What is the solution for this, any idea frnds.
Me using honeycomb, me tried but with fragment but didnt get a good sample for that. Me now mainly trying that,
if anyone can give me some links for that it will be
great
First of all: open your dialog using the showDialog method (there are a lot of examples in the official documentation). If you do so, the activity will take care of dismissing the dialog on destroy, and re-showing it after the activity has been recreated.
Also... if the dialog shows a progress bar (not a wheel), you will want to update the progress of the dialog after orientation changes. In order to do so, I recommend to use the onRetainNonConfigurationInstance to return the current state of the dialog and/or the activity itself. Then, you can use getLastNonConfigurationInstance to recover that state. Google about those two methods if you want to see examples.
Another thing to keep in mind: if you are updating the state of the dialog an/or any other UI element from the AsyncTask, you must be aware that after the activity is recreated, the AsyncTask may be pointing to the wrong UI references. In order to handle this, you can create a proxy class (Proxy design pattern) to detach the AsyncTask progress notifications from the current UI elements.

Best way to terminate a wizard in android

I have a reservation wizard in android, when i say wizard i mean i have multiple activities (meaning screens) that are passed from one to another until booking is complete. in each step of the way my info may be invalid and so ill have to back track 2-3 activities and start all over, all the activities i back tracked should be destroyed, they may need to invalidate a singleton data container that they filled with their data.
I thought of 2 ways to do this:
start all activities related to the wizard with startActivityForResult() so i get notification when an activity is finished and with which error code (finished OK or error occurred) and act accordingly (for instance: if in the middle an activity fails it will return failed and the previous one will return failed as well until i get to the wizard's first activity where i either declare the error with a dialog or show the 'thank you' screen.)
I can send an react on intents with certain parameters so i have a 'close and clean' intent message that close down the previous activity etc...
which way is better, any other interesting\efficient way to do this ?
I Got a hint that got me thinking in a different direction:
use an invisible Activity, or alternatively , a local service,that is the 'brains' that known on each turn of the way what action is to be taken. to remove a complete stack of unneeded activities i should use the FLAG_ACTIVITY_CLEAR_TOP on the bottom most activity i want to use next.
Another options is to enclose all
the activities i want to play with
their pposition on the stack inside
an ActivityGroup Object which keeps
all activities alive (like in Tab)
and on the stack, but you control
which one is displayed and which is
not. the activity group will contain
the state machine logic regarding
which Actvity should not be
displayed and which should be
disposed.

Android: When to use Dialog vs. Activity

When is it preferable to use a Dialog box as opposed to an Activity in Android? From my understanding, anything you can do with a Dialog box you can also accomplish with an Activity. Are there any tasks that can only be accomplished by an Activity or a Dialog?
Is what you're doing worth a new Activity? Do you need to be able to start it through an intent? Do you really need to create a new Java class for it?
If it's a straightforward dialog that displays a text and has simple hooks for positive/negative/dismissal functions, definitely use a dialog.
If you have something complex, you may want to go for a full-blown activity.
Well why exactly would you want to start a new activity just to ask the user "Are you sure? Y/N"? Dialogs generally run on top of the activity, and are usually smaller activities or notifications for the user. They also usually have something to do with the process of the app running. It helps make things simpler to open a dialog to prompt the user on top of your activity, than to start a new activity atop your current activity.
I went for Activities when I needed an user interaction that needs backstack, navigation, lifecycle and callable features.. else with dialogs. Being from the WebApp world I ask whether I would have needed a new server page or a pop window for an interaction and the decision in Andoird world becomes easier!
If newServer page then mostly Activity
elseIf popUpWindow then dialog
I created my android application in one fragment with nested alert dialog, so far my application still running well in handle those nested dialog, and I think dialog is less consuming memory than an activity

Categories

Resources