In what order should I call events in this logout sequence? - android

Writing a kotlin social media app. I want to do 3 things within the logout sequence:
logoutbutton.setOnClickListener() {
//1. db.logout()
//2. finish()
//3. go to login screen
}
Does the order of events matter here? This is the order I am going with right now, but I don't know where the best place to put finish() would be.

Call finish when you want the current activity to popped off the activity stack. You typically do that when the user has indicated they no longer want to interact with it. Other than that, the order of these things don't really matter.

A trap that has caught me a few times is that finish() is actually asynchronous, so can give the illusion that instructions following it are "safe"... until they take a little longer and the activity gets torn down before they complete.
That can make for very difficult bugs to find.
I suggest for safety, call finish last.
I'm assuming db.logout may take some time to complete and/or may have to run on a background thread so some caution may be needed there. Fortunately Coroutines can help a lot .

Related

Prevent kotlin coroutine from being interrupted even if user navigates away

In my code, a method performs three API POST and it takes a while for each of those to complete. I'm using kotlin coroutine launch on that method. But I also want the user to be able to navigate away from the page while the task is running. I don't want the task of performing three API calls to be interrupted when navigating away. What is the best way to do that? Is WorkManager the way to go?
Somehow my question is similar to this but I need to do it in Kotlin. Is the answers in that post still relevant?
You need a Service. Please read this:
https://developer.android.com/guide/background

Android MVP - Detaching view (onPause VS onDestroy) and state preservation

I'm trying to implement the MVP architecture in my app.
However, after reading some blogs and viewing some sample project samples, I'm not sure I completely understood where is the right place to detach the view, and what should be done once the view attached for the second time after an async operation.
Most of the examples I saw, just sum it all up with a view's null validation check after an async call.
I'll try to make my point clear with an example - Login/Registration by phone number (The main idea is the important thing, and not the example itself)
There is an activity which display a fragment - LoginFragment.
The user enters his phone number and tries to login.
If the user exits - he should get navigated to another activity (after entering the code received by sms..)
If the user doesn't exits, he should get navigated to registration process - RegistrationFragment.
If there was an error, a dialog with error message should appear, ErrorDialogFragment.
Now, in a happy flow where the user presses the login button and waits until the process complete, all good.
But, in a less happier flows (not so frequent ones, but definitely can't get ignored), the user presses the login button and after that presses the home button or alternatively gets a phone call.
In scenario 1, where we attach/detach the view in onCreate/onDestroy, once the async login operation finish and we should replace to RegistrationFragment or show ErrorDialogFragment, there is a chance we will meet the famous IllegalStateException:
getting exception "IllegalStateException: Can not perform this action after onSaveInstanceState"
In scenario 2, where we attach/detach the view in onResume/onPause, once the async login operation finish we won't be able to replace fragment or show a dialog because the view is already detached.
In this case, I'm not sure what is the right thing to do.
Should we go with scenario 1 and commit the transaction with commitallowingstateloss?
I'm afraid it is a bad idea.
Or Should we go with scenario 2. In this scenario, we should act accordingly when view attached again, which means saving states (RegistrationRequied, ErrorHasOccured, LoginProcessStillRunning, etc..) in the Presenter/Interactor.
Can someone can shed some light regarding this?
Thanks in advance!
Oh the joys of the Android lifecycle. I feel your pain.
In my personal experience, resorting to commitAllowingStateLoss is usually a symptom of trying to update your Ui (View) while in the background (and as you note, the ui may be destroyed).
What I would suggest is that you don't try to update your ui without checking if the activity has been backgrounded (onStop or onPause depending on the situation). If your ui has been backgrounded, remember the changes you need to make and do them when your Ui is reconnected (onStart or onResume depending on the situation).
In essence I'm saying you should follow Scenario 2. And yes. You will have to save quite a bit of state somehow.
Unfortunately this isn't easy and there are many approaches to doing this ranging from using event buses, all the way through to using RxJava.
Every approach has it's advantages and flaws and they are all really too complex to discuss in detail in a single post.
However, I have a blog post I wrote some time ago on a way of doing this in a way that doesn't require additional libraries.
It's a little out of date now, but it may give you some ideas: A Simple MVP aproach for Android
All the best.
Kind regards,
Chris.

waiting for keyboard input

I'm writing an app using Android 2.1
At some point, I call setOnKeyListener
In particular, I write...
editfield=(EditText)findViewById(R.id.edittext);
editfield.setOnKeyListener(this);
This is in the main thread, in the onCreate callback.
At this point in the code, I would like the processing to stop and wait for the
keyboard input. If I let the code run on, the logic will break, soon enough.
I suppose I could put the machine in a wait loop until a keystroke invokes the onClick method. I could also create a wait loop at the point where the input from the user was required. But I don't feel comfortable with either of these solutions. (A related problem is this -- at a certain point in the code, the screen must be lit up. Must I check this before proceeding past that point?
Perhaps I'm not good with documentation, but I have not been able to find anything specific that answers these questions.
Can someone explain to me how to accomplish the timing I need and, more generaly, where I can find info on these questions?
Thanks in advance.
-looking in DC
The Android key system is event-based, it does not work like the old ask-and-wait mechanisms of C/C++ etc for obtaining user input.
If you blocked/waited - then what would happen if the user pressed the Home key (you can't catch that) or navigated to another app - your app would force close because it would still be waiting and your onPause etc would not execute.
My suggestion would be:
Put all the code that should occur after the click into some function
Place the listener at the end of onCreate, this way no more code will be executed after you set the listener
When you get a key-down, call your function. Thus the statements in your function will only execute after a key down
If however, this is for a game, then it is acceptable to have a thread dedicated to touch/key-events which sleeps for 50s or so to avoid event overload (but this must not be the main UI thread!)

Android Best Way to Detect and Handle User INACTIVITY

Inactivity is a very important EVENT. For many apps if the user does not interact with it for a certain number of seconds its time to reset the app and go back to main activity logout, or conserve power. So I would really like to get some feedback on the best way to detect this. In fact I think everyone will benefit from a good solution to this.
So my question is twofold:
1) Is there a better way to detect user inactivity than using a combination of
activity.onUserInteraction() to reset a CountDownTimer?
Note: One reported downside to this approach is that softkeypad interaction might not be
caught by this approach.
Note: Another reported downside is the CountDownTimer is off main thread and might not update
correctly. I am not sure how big an issue this is?
Note: CountDownTimer appears to have cancellation issues as well:
how to stop/cancel android CountDownTimer
2) Lets say that onUserInteraction()/CountDownTimer is the best/only solution to this problem
there are still some questions:
a) should each activity launch its own countdown timer?
b) Should a single countdown timer be restarted in the onCreate method of each activity?
c) lets say I want to dim the screen or goto main activity when the countdown expires where
should the timeout handler be located? In each activity? In a service?
Thanks
Just stumbled upon this question as I've answered something similar just now.
Personally, I'd opt for option 2 that you have suggested, and put a timer into a singleton so its available across all activities. Theres no need for a separate countdown timer unless you have a specific requirement to react different under different features of your application.
Why would you want to reset the timer in the onCreate? You should do that each time the user interacts with the application, such as in the activity.onUserInteraction() method.
To quote from my previous answer:
You'll need to invest a little thought into exactly what your
requirements are here, but from what I can tell, you want to keep
track of the user interactions and if a time limit expires since the
last interaction, perform some action, in your case logging them out
of your application.
Firstly, you'll need some place that you can track when the last
interaction occured, since you'll want this to be application wide you
could use a singleton to hold this, or override the Application class,
either way should do.
Next, you'll need to start tracking user interactions. From your
activities, you can override the onUserInteraction method, this gets
invoked anytime the user interacts with the application such as key
event. Each time you hit this method, update your singleton and let it
know something has happened, with a timestamp.
Finally, you'll need some kind of looping check to constantly check if
anything has happened recently. Theres various was of doing this, you
could have a continuous loop that compares current timestamp to the
last recorded event, a bit of draft code :
while(true)
{
if (timeLastEventRecorded < (now - 15))
{
//nothing has happened in 15 minutes, so take corrective action
}
}
Presumably you'll already have some code in your application that
takes care of logouts, such as when the user clicks "logout", you
should just be able to invoke that in the sample above.

Android lifecyle question re: incrementing a counter

My android application tracks the number of correct answers while the user is in process of taking a quiz. If the user's answer matches the correct answer, a counter to track this is incremented. This logic takes place in the "onResume" method.
The problem is, if the user presses the home button from this activity, then re-enters the application, it resumes at this activity, and the counter gets incremented again.
The only solution I can think of is to set the correct answer field to a "magic number" such as 99 when a correct answer happens, and check for that first before going into the answer-checking logic. If it's 99, then skip the answer-checking logic and just redisplay.
Is there a better way to do this?
I'm not quite sure about the real problem you have and in specific why you're incrementing a counter of correct answers in the onResume event. You have for sure some kind of button where the user confirms his answer. Don't you verify the correctness of the given answer there, i.e. in the button's click method?
Implementing such logic in the onResumeevent is somehow dangerous, because it is called by the underlying Android OS.
It seems like you are using an application lifecycle method to cause a non-lifecycle effect. Please post some code. If you are relying on onResume to indicate that you have returned from a different Activity, you should take a look at startActivityForResult. If this isn't the case, you'll need to post some more description of your program. You shouldn't, however, be using onResume for anything besides setting up your applications state, since you can't always control how its called.

Categories

Resources