Select activity depending on Room - android

When I launch my app, I should select start activity, depending on Room data. Like this:
If there is no user (by login string, stored in preferences) - show entrance Activity.
If there is a user but his propertyA wasn't set (null by default) - show Activity where he will select it's value (non-null afterwards).
Otherwise show general Activity.
The first option can be easily checked, because we can load value from preferences immediately. But to check propertyA I need to get user by login and Room forces doing it only in background, so we need async logic here.
The options to solve this I see:
Show Activity from step 2 (or some temporary Activity), update to necessary when user is ready (loaded). Bad because user will see wrong contents. Moreover, to avoid unnecessary updates we should store last property value - so we change to general Activity only when changing from null to something else (this way we get code mess for simple task).
Room database's allowMainThreadQueries(). Bad because breaks Room's general idea.
Semaphore (on main thread, but with expectation user loading is a fast task). Bad because looks ugly in code and has same problem as step 2.
I suppose my approach is totally wrong (in architecture way). Can you suggest how it can be solved in more elegant way?

Honestly, with your issue, I wouldn't go for any of the three options you listed.
Since your app relies on fetching data before knowing what content to show to the user, why not use a Launch Screen?
Launch Screens were added to Material Design and it's a good option if you wish to do some initial start-up processing while not sacrificing aesthetics or risk displaying inaccurate data.
Here's a link to Launch Screens: https://material.io/design/communication/launch-screen.html
Even if you don't use either a Placeholder UI or a Branded Launch Screen, it's still more pleasant to just show a short animation to the User as your app queries if propertyA is set.

Related

Ideal way to tackle pending data changes (when to save changes)?

I have a rather peculiar case on my hands, and Im surprised that noone seems to have written about it/something similar for Android (or my Google skills suck)
Situation #1:
User can input text into field1 and field2.
User can also re-arrange items in a list (displayed in a RecyclerView)
Whenever the user does any of the edits, the UI is already showing the updated data (e.g. editing field1 will show the text as the user types it, and the list of items will show them in the new order as the user re-arranges them).
Saving the data right away here will trigger the UI to refresh (to display the same thing) and give the user a bad experience (field1 focus will shift to the first letter, and the app might crash if the user quickly re-arranges list items).
So it makes sense to store the edits and execute them at a later point.
Situation #2:
User can tap plus/minus buttons to increase/decrease a value
User can input text into field3.
As in situation #1 above, editing the field will already have the UI in the updated state. But, in this case - tapping the plus/minus button will also update the data, but the UI will not be updated (unless the data is saved, and the query ran again...).
Problem:
If data is saved immediately as the user performs an edit, besides doing a lot of saves, it makes for a bad user experience as the UI will refresh in some cases whereas its already up to date.
If the edits are tucked away and performed at a later point, the UI wont refresh.
Im using MVVM, so all performed actions are sent to the viewmodel and it decides what to do. I find myself looking for a solution that works differently across different screens of the app, but I know that would just be shooting myself in the foot and then jumping off a bridge. Surely, there must be someone out there that has come across this challenge and had some insights around it?
Ideal solution: One solution that just works for all the different screens. Do you have it? Please let me know.
/ Desperate Android Dev
First of all, let me start by stating that I don't think there is a correct answer here, but you should consider what your own app does and then determine what you need to do.
Let me explain. Consider two application, one that saves TODO items and the other is a banking application.
I will now explain what I think could work for your application, since you have not mentioned explicitly any requirements that contradicts that.
In situations like that, I believe being optimistic is a good idea. Assuming that things will not fail, and when they do, try to back out. What does that mean?
That means, for example, in the scenario you mentioned, user enters something in a field. You should let the UI update automatically (Nothing we do here, that's just Android), when that happens you save those changes either locally, or to a server, doesn't matter.
Of course, you can optimize, instead of saving each letter, throttle the input somehow, but you get the idea.
This can either be a succeed or a failure, because we are optimistic, we let the UI update and the user get the feel that our application is lighting fast. You don't need to reload anything, or refresh anything. The UI should match your Model state now already.
What if the things go south, and your HTTP request or DB update fails for some reason, then you need to take action. But try to keep your reaction appropriate.
You can handle that failure in so many ways, again, depending on how critical what you are doing in your app really is.
You can just show a Toast, or even do nothing if the user action was so trivial.
You can show the user something a bit more concrete if the action is of some significance, maybe a Snakbar with retry and explanation of what happened.
You kill your process and finish all activities -kidding don't ever do that- but showing a very intrusive pop-up and possibly reverting the UI value to the correct one, if what the user was doing is quite critical.
Now this approach doesn't just give the feel that the app is really fast, but it also keeps things simple.
Another advise is don't try to solve problems that don't exist yet, that means don't start implementing background services and job queues for some local persistence jobs that never outlive a view, and could never will.
Instead, use measurements, log those errors and failures with some tool, and use those stats to know what needs to be fixed -if any-
Back to our two applications, this approach might be perfect for a TODO app, however this might not be too good for a banking app.
Assume the user transfers money, we say immediately, ALL GOOD MATE! and then the request fails and your user's landlord kicks him out for never paying rent.
So it all comes to how sensitive the operations your're doing.

Is there any way to alter the behaviour of Android restarting Activities after a crash

After reading through all the questions on SO regarding this topic i am extremely annoyed by this.
Crashes will happen, no one writes perfect code. And there are apps that require a certain logical hierarchy. The best example is the login-screen idea, where you are in some activity doing something on a server and now the app crashes. After a restart, the app lost all its login-session data and saving it might not be the safest idea. So presenting the user with the login screen after a crash would be the best and most logical thing to do. The best user experience.
However Android decides to remember the Activity stack but only restart the last working activity with a "blank" application under it.
The only viable option i see would be to check in EVERY single activity if some login state is available or not and if not, start the login (launcher) activity with a clear-top or clear-task. But this almost forces you to write a base extends Activity class in which this behavior is implemented and then all activities have to extend that. But what if, for some reason, you cannot extend it because you need to extend some other type of activity?
There is android:clearTaskOnLaunch but this happens every single time the user returns from exiting via home button. There is the antagonist finishOnTaskLaunch that finished an activity every time the user presses the home button. So the Android devs are aware that sometimes one would like the app to appear in a certain state after exit but a crash seems to be exclusive to all that.
Using a custom UncaughtExceptionHandler gives me some chance to act after a crash but as the apps state is unrecoverable i can only perform certain tasks that will happen in addition to Android very own behavior.
So my simple question is, if there is any way, that is built into Android, that allows me to change the after-crash-behaviour of Android in a natural way that does not depend on the version it's running (to some extent ofc) and will result in a somewhat smooth user experience.
I would say the proper way of obtaining the result you would like would be to provide a proper parent or up navigation stack. You can read about it more here https://developer.android.com/training/implementing-navigation/ancestral.html.
But the gist of it would be to use the idea of parent activities to provide proper back navigation. If the activity already exists it will just go back to it, if it doesn't (such as in the crash scenario) it will launch the correct activity when the user navigates back.
NavUtils is a handy class to help build this behavior and is part of the support library which would work on a range of different API levels.

Android UI reliant on data from webservice - data doesn't come back in time

I have a screen in my application that is just a bunch of links. I am being directed to get the URLs from a web service so that they can be changed whenever and no android code would have to change. My problem is though I ask for data from AsyncTask and it does not come back before the user access the screen and then the links are either not there, or go back to a hardcoded resource I put in. Is there a better way to get data that affects the app like this?
why not just put in a progress dialog and then dismiss it in the onPostExecute? that way the link is always there and they cannot get ahead of the call
It might be a good idea to cache the links, so that the screen isn't blank, at least after the first time you run the app. You can update the list every time the user opens the page.

How to save the user's selection for every time they run the app on Android?

The first time the app is run, I want to have a checkbox list appear where the user selects the list items that they are interested in, and run the program based on that. Every subsequent time the app is run, I want those selected settings to be remembered, or changed with an options menu, in which case the new settings will be remembered. But all I know how to do is make an app go from the beginning every time it is run...
Similarly, my app reads sequentially through all the data in a large, read-only, unchangable database. As of right now, it creates and opens and fetches all the data every time, which takes a few seconds at the start of the program to open up and do anything. Is there a way to get around this, or, is it even a good idea to try to get around this?
To remember the users selection, have a look at SharedPreferences. You can store the selected items there.
To the database: That really depends on your app. If you need all that data at the same time in memory, I guess theres no way around loading it at the start. If you only need parts, it would be a good idea to load a part of the data when required. But without exact knowledge of your app/use case, this is hard to tell.
When you have some sort of "lag" when loading the database: Do you probably load the database in the UI-thread (= without creating a seperate thread for loading)? Thats bad practice since it blocks all UI operations. Have a look at AsyncTasks. Thats a handy class that wraps around a thread and lets you do things in the background without blocking all the UI. After it's done with its task (loading in this case) it provides you a onPostExecute() callback where you can update your UI with the loaded data.

how to handle "save" and "cancel" buttons and the back key

I am wondering how to handle user input forms in my app. (real budget lite). Right now this is what I am doing, but I am not sure if this is the best practice:
I have two soft buttons on most of my activities that take user input: "save" and "cancel".
"save" captures the user input and then finishes the current activity
"cancel" abandons any user input and finishes the current activity
Hitting the back button on the device does the same thing as "save"
It still bothers me a little that the back button performs the function "save and go back". Users who are new to android phones are probably used to web browsers, where the back button means "forget about this page and go back to the previous page". If you were buying something online and you got to the final "purchase" page, you would not expect the back button to complete the purchase, would you? But it seems like that behavior is the way that the built-in applications work, so I am not inclined to do it differently.
Anyway, I have looked through the official documentation and I cannot find this behavior explicitly spelled out. Can someone point me to the right place, or at least provide some guidance as to best practice?
The choices as I see them are:
Do it the way I am doing it now.
Get rid of the "save" button and count on the users knowing that back equals save.
Get rid of both buttons and provide a cancel feature from the menu key.
The google contacts app provides the buttons "done" and "revert", by the way. I guess "revert" means cancel; is there a difference? Maybe I should have my buttons labeled "done" and "revert" instead of "save" and "cancel"? In gmail, the menu button provides the choices "save draft" and "discard". It seems to me that we would be doing the users a favor if we had some consistency here.
Thanks in advance.
But it seems like that behavior is the way that the built-in applications work, so I am not inclined to do it differently.
The only built-in application that does this, that I can think of, is the contacts app, and I find that UX to be lousy. I was just cursing at it yesterday, as it happens.
Perhaps other built-in apps do it too, but I haven't encountered it yet, at least not that I recall.
Anyway, I have looked through the official documentation and I cannot find this behavior explicitly spelled out.
There are no UX guidelines of this nature in the documentation. Unfortunately.
It seems to me that we would be doing the users a favor if we had some consistency here.
You would get no argument from me.
Personally, I think of the BACK button as behaving as a "cancel", or whatever the negative choice would be. Dialogs typically behave this way on Android, for example.
If you have existing users, and you have established communications with them (newsletter, support Google Group, etc.), I'd poll them and see what they think. In the end, it is what your users want that matters most.
In a pinch, make it configurable. Ideally, for something like this, there is One True Right Answer, and therefore configurability would be pointless. However, if your poll indicates a split vote, and in the absence of Android platform UX guidelines, a setting might be the right solution for you.
UPDATE: I wrote a blog post about this issue, as I think it is reasonably important and worth a bit more prose.
I highly recommend you following the model used by the standard Android and apps, where editing always happens in place. That is, there is no "save" button -- the changes you are making are effectively being saved as they are being done. (The implementation may of course be slightly different, but to the user this should not be visible.) Following that model, your buttons should be something along the lines of "done" and "revert". This helps with the user's mental model of what is going on, that leaving the activity would not be likely to turn into a "revert" operation.
One reason for using this data editing model is that you will run into many fewer bad edge cases. If you try to present a more traditional model where the user explicitly saves, then any path the user may take out of your activity is a potential cause of data loss, which then leads you to want to protect them from that, and thus trying to show dialogs to confirm that they really want to lose their data. This is a losing battle, and you will never be able to catch all of the holes out, and your UX will suffer for it. (Consider for example if they receive an incoming phone call, this is just not the time to put up a dialog to first ask them if they want to save their data, nor would you be able to anyway.)
So start with your basic model being edit in place. This is consistent with the convention the standard platform uses, and this was deliberately chosen in the platform design because overall it results in a much simpler and more consistent and comprehensible UX. Design your UI flow to emphasize this model, by avoiding explicit "save" actions.
For me, I always feel 'unsafe' without a save option. For example, in GTask, when you create a new task, hitting 'back' (hard button) will save the stuff and back to prev screen. There's no soft button BTW. But I always frustrated about this.
For your app, I think you need to consider two things before deciding which way did the back button perform:
How critical is your 'save' operation (like it will place orders!)
Did your user expected to cancel stuff?
Obviously, if the save is long-processed and critical, an explicit control must be taken. (and back would not save); and for the second point, I guess GTask considered jotting notes should be quick and simple, and it should feel like jotting on paper --- it's saved, once you wrote.
Referring to what you said, back in web browser is go back and forget everything. But at the same time, Google (e.g. Google Docs) is also doing auto, background save, that it's not 'forgotten' when you back.
Trying to decide a universal action for when the user presses back makes this question a lot more difficult (if not impossible).
A much simpler approach is thinking about the context, and I see two main situations: the user is interacting with a dialog and the user is interacting with a regular activity.
Interacting with a dialog
If an user presses back in a dialog (for instance date time picker dialog) it's because he doesn't want to see that dialog or change that information.
While in a dialog, the user doesn't expect changes to apply until he says so (by pressing "Ok").
Interacting with an activity
For example, the user is seeing the details of some item that your application provides (contact information). Pressing back after some changes could mean "now take me back to the list of contacts". Anyway, this is not 100% clear. So including options to save and discard changes (call it whatever you like) could be a good option.
My thoughts as an android user
The behavior in a dialog is simple and clear. I think we have no doubts about it.
In activities, I'm used to have the back key to save data and send me to the last activity. Whenever I want to discard my changes, I find myself pressing the menu button and looking for a button to cancel.
If you want to something better, include the default behaviour as a preference and/or display a toast when you cancel or save the information.
Cancel vs revert
In practice, they do the same thing. Cancel should, herr, cancel what you are doing right now (editing something). This should/could take you to what you were doing before (list activity).
Revert will change the state of what you are seeing to the way it was before you started doing changes. This may not take you to the previous activity. It could simply update the UI to the original values.
Experiments with contacts application
Pressing back while editing a contact will save the changes.
Pressing home while editing a contact will discard changes

Categories

Resources