joshhendo
joshhendo

Reputation: 2014

Android: Proper way to handle Activities

Firstly, I'll explain the situation I'm in with my applicaton before I get onto the main question I have. Firstly, I want to find out if the way that I am handling activities is a proper way of handling activities, as I feel it might well not be which in turn is causing my problems.

Currently I have 3 activities setup. Main.class, Login.class and Display.class. The Main activity doesn't have any UI associated with it at all, it launches other activities. So, the first activity that get's launched when the app is launched is the Main activity, and it goes and reads from a SharedPreferences store whether or not the user is logged in. If they aren't logged in, it will open up Login.class, if they are logged in, it will open up Display.class (both of which have UI's associated with them). It uses startActivityForResult().

Because of the way I decided to go around working with activities, I needed to override the back button on both Login.class and Display.class: otherwise, it will go back to the Main.class, and re-run the launch activity sequence, which will inturn re-launch the activity that was just running (therefore the back button is useless). So, I overrode the back button to send back an integer of -1 and then finish() the current activity. I've overridden the onActivityResult(int, int, Intent) for Main.class, and if it receives a -1, it will finish() as well, instead of trying to re-launch the activity.

Now, that all worked for how I wanted it, though I have a feeling that it's the completely wrong way to handle activities, and it's causing problems for me later down the track.

In my application, I decided I wanted to put an app widget and a notification in, both of which will open the app when clicked (via an intent that launches Main.class). I got it all working so that it would do that, though it seems as though starting a new Activity causes problems.

What happens is basically, if the application is already running, and someone pulls down the notification and clicks on it, it will open up a new activity of the same application. This is problematic, especially with the way I handle back buttons: When you open a new one, and press the back button, it will close the new one (as expected,) but will then take you back to the OLD one. You can then press the back button again and exit it, but obviously I don't want to release an app that needs the back button to be pressed twice. What is the best way to sort this problem out? I'm happy to completely change the way I handle activities if that's a major part of the problem.

Thanks, Josh.

Upvotes: 2

Views: 1805

Answers (3)

Aleadam
Aleadam

Reputation: 40401

A feasible approach is to have a class extending Application and a couple of Activitys bound to it. A private boolean logged value can determine whether the Display needs to call LogIn to foreground.

public class MyApp extends Application {
    private static boolean logged = false;
    private Activity logInActivity;
    private Activity displayActivity;
    public void onCreate () {
        super.onCreate();
    }
    public void setDisplayActivity (Activity act) {
        displayActivity = act;
    }
    public void setLogInActivity (Activity act) {
        logInActivity = act;
    }
    public void finishActivities (Activity act) {
        activity.finish();
    }
    public void setLogged (boolean logged) {
        this.logged = logged;
    }
    public boolean isLogged () {
        return logged;
    }
    public Activity getLoginActivity() {
        return logInActivity;
    }
    public Activity getDisplayActivity() {
        return displayActivity;
    }
}

class Display extend Activity {
    private MyApp app;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        app = (MyApp) getApplicationContext();
        if (!app.isLogged()) {
            // start LogInActivity. After log in, it will call app.setLogged (true);
        }
        else {
            // continue with Display;
        }
    }
}

Upvotes: 1

BonanzaDriver
BonanzaDriver

Reputation: 6452

Actually how you set a -1 (which is fine) and then call finish() is perfectly acceptable. I forget the property values, but if you want only a single instance of an Activity there is a way to set that in the manifest ... Task affinity or one of those values - you'll have to look it up.

As an alternate, you can override the Application class and use your own to manage application state. Think of it as a singleton tracker for the main Activity .. "if it already exists use that one, otherwise create a new instance" kind of thing. When creating your main Activity set a reference in your newly extended Application class (make sure you null this out when main is shutting down), then check to see if a reference is available when onCreate() fires again ... if there is a reference already there use that instance of Main .. if not, proceed as normal and set it.

Food for thought ...

Upvotes: 1

davidcesarino
davidcesarino

Reputation: 16228

I have a feeling that I don't fully understand the depth of the problem, so please forgive me if I'm saying something that you already tried.

But couldn't you remove Main and launch Login from Display? I mean, makes more sense. That's what I do here all the time when I need accessory activities that must fill data for the main activity (which is obviously Display in your case). And when you return from login, you could do all the checks you need. You could allow, say, a "read-only" Display, you could provide a dialog warning...

You would save a lot of trouble and useless code indeed (most of the result/intent spaghetti).

Upvotes: 1

Related Questions