11:06 AM
0
Before I dive into the launch mode of an activity, we need to first understand the term, 'Task'. A task is the stack ("Last in, First out") which contains a collection of activity instances. Normally, when a user starts an app a new task will be created, and the first activity instance is called as a root of the task. The Android system can hold multiple tasks at the same time and only one task is in the foreground. Similar to a double click of the home key on iOS, if you long press the HOME key on Android you'll be presented with a list of your currently running applications. You can select any one of these applications (which are currently running in the background) in order to bring it to the foreground and interact with the app! Of course, because background tasks do tend to use up your processor cycles you should try to keep your backgrounded apps to a minimum to ensure your phone performs optimally.
Now let's look at the launch mode of an activity. Launch mode allows you to define how a new instance or the existing instance of an activity is associated with the current task. The activity launch mode has four valid values:
1
<activity android:launchMode = ["standard" | "singleTop" | "singleTask" | "singleInstance"] ../>
The 'standard' is the default value. The four values fall into two groups:
  • 'standard' and 'singleTop' can instantiate multiple activity instances and the instance will stay in the same task.
  • For 'singleTask' or 'singleInstance', the activity class uses the singleton pattern, and that instance will be the root activity of a new task. Let's examine each value:

"standard":

Multiple instances of the activity class can be instantiated and multiple instances can be added to the same task or different tasks. This is the common mode for most of the activities.

"singleTop":

The difference from 'standard' is, if an instance of activity already exists at the top of the current task and system routes intent to this activity, no new instance will be created because it will fire off an onNewIntent() method instead of creating a new object. Let's take the Twitter-oauth integration as example. Suppose we have the following NewsDetailActivity declared:
<activity android:name=".NewsDetailActivity" android:launchMode="singleTop"> <intent-filter> <action android:name="android.intent.action.VIEW"></action> <category android:name="android.intent.category.DEFAULT"></category> <category android:name="android.intent.category.BROWSABLE"></category> <data android:scheme="oauth" android:host="twitt"></data> </intent-filter> </activity>
view raw singletop.xml hosted with ❤ by GitHub
And in the activity we will have the following code to start the oAuth process which will bring up the browser to visit Twitter's authorization page:
private void twitterOAuth() { try { System.setProperty("twitter4j.http.useSSL", "false"); System.setProperty("twitter4j.oauth.consumerKey", getString(R.string.twitter_oauth_consumer_key)); System.setProperty("twitter4j.oauth.consumerSecret", getString(R.string.twitter_oauth_consumer_secret)); System.setProperty("twitter4j.oauth.requestTokenURL", "http://api.twitter.com/oauth/request_token"); System.setProperty("twitter4j.oauth.accessTokenURL", "http://api.twitter.com/oauth/access_token"); System.setProperty("twitter4j.oauth.authorizationURL", "http://api.twitter.com/oauth/authorize"); // get the instance Twitter twitter = new TwitterFactory().getInstance(); twitter4j.auth.RequestToken requestToken = twitter.getOAuthRequestToken(CALLBACK_URL); //save the request token and secret prefsManager.saveTwitterRequestToken(requestToken.getToken(), requestToken.getTokenSecret()); //save other data persistNewsDatas(); //start the browser activity Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(requestToken.getAuthenticationURL())); startActivity(intent); } catch (Exception e) { Log.e(TAG, e.getMessage(), e); Toast.makeText(NewsDetailActivity.this, "Fail to connect to twitter now, please try later.", Toast.LENGTH_SHORT).show(); } }
So if a user goes to this activity in the current task (let's say Task #1), a new instance of NewsDetailActivity will be pushed to the top. Now start the oAuth process and the Android system routes the intent to the default Android Browser application, whose launch mode is 'singleTask'; that means a new Task begins for the browser activity, let's say Task #2. Hence the 'NewDetailActivity' is still on top of the Task #1.
After the user finishes the authorization on Twitter's page, the customized callback url 'oauth://twitter' will be invoked. Because NewsDetailActivity declares support for that data type, the system routes the intent to the 'NewsDetailActivity'. Since NewsDetailActivity's launch mode is 'singleTop', and the top instance on Task #1 will be reused, its onNewIntent() method will be invoked to continue oAuth's last step. Here is the code for that:
protected void onNewIntent(Intent intent) { super.onNewIntent(intent); Uri uri = intent.getData(); if (uri != null && uri.toString().startsWith(CALLBACK_URL)) { String verifier = uri.getQueryParameter("oauth_verifier"); try { //load other persisted data goes here .... //get the request-token from prefs and request the access token TwitterFactory twitter = new TwitterFactory().getInstance(); requestToken = prefsManager.getRequestToken(); prefsManager.clearTwitterRequestToken(); twitter4j.auth.AccessToken accessToken = twitter.getOAuthAccessToken(requestToken, verifier); // save the access token prefsManager.saveTwitterOauth(accessToken.getToken(), accessToken.getTokenSecret(), accessToken .getScreenName()); //other logics to do the post to twitter .... } catch (Exception e) { Log.e(TAG, e.getMessage(), e); } } }
view raw onNewIntent.java hosted with ❤ by GitHub

"singleTask":

A new task will always be created and a new instance will be pushed to the task as the root one. However, if any activity instance exists in any tasks, the system routes the intent to that activity instance through the onNewIntent() method call. In this mode, activity instances can be pushed to the same task. And if the user clicks the BACK key from the singleTask activity, the system will return the user to the previous activity.
This mode is useful for activities that act as the entry points. For example, in a tab-based Twitter client, we can declare the main TabActivity as singleTask. This is also useful if you only want a single instance of the activity to be created. One example of singleTask is the Browser application. Let's take a Twitter-client-application as example, where the main activity is a TabActivity and has three tabs: tweets, replies and messages. And we want to suppose auto-refresh and notification function when app is running.
In AndroidManifest.xml, we have:
1 2
<activity android:name=".MainTabActivity" android:launchMode="singleTask" android:alwaysRetainTaskState="true" android:windowSoftInputMode="adjustPan">
</activity>
view raw singleTask.xml hosted with ❤ by GitHub
Suppose we have the notification for new tweet/replies/messages, and we hope that clickong on the notification will take the user to the current TabActivity, and switch to corresponding tabs. (Here we suppose the app is not closed before user clicks the notification). Because the MainTabActivity's launch mode is singleTask, system routes the intent to the MainTabActivity by calling its onNewIntent() method. And in this method, we can determine which tab to switch to according to the bundle data in the intent.

"singleInstance":

Same as 'singleTask', except that the no activities instance can be pushed into the same task of the singleInstance's. That means, the activity with launch mode is always in a single activity instance task. This is a very specialized mode and should only be used in the applications that are implemented entirely as one activity.

Summary:

Understanding the launch mode will help you design better navigation and implement some special cases. Here we only discuss the launch mode from the AndroidManifest file. Android launch mode can also be declared using the Intent flags, such as FLAG_ACTIVITY_NEW_TASK, FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_SINGLE_TOP. And we will create more posts to talking about intent flags in the near future, so stay tuned!

for more informations: http://www.intridea.com/blog/2011/6/16/android-understanding-activity-launchmode

 


0 comments:

Post a Comment