Activity的四种启动模式是相当重要的知识点,给activity设置合适的启动模式有利于程序的运行。
四种启动模式中,singleTask,singleInstance最为重要。
Activity A设置为singleTask,能够保证Activity A在栈中只有一个实例,这个栈也允许存在其他的实例,无论是Activity A是在栈顶还是栈底,当有新的intent请求Activity A时,都不会创建新的实例,而是直接交给Activity A的实例来处理。
和这个模式相关的方法有onNewIntent,用来处理新的intent请求,特别需要注意的是使用startActivityForResult方法的时候,根据startActivityForResult的api说明
- if the activity you are launching uses the singleTask launch mode, it will not run in your task and ts you will immediately receive a cancel result.
对于这句话不是很理解,不知道“if the activity you are launching”指的是被启动的Activity还是启动的activity,写个例子验证一下:
- public class HomeActivity extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Button btn = new Button(this);
- btn.setText("start camera");
- LayoutParams params = new LayoutParams(200, 60);
- params.gravity = Gravity.CENTER;
- btn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent();
- intent.setClassName(HomeActivity.this, SecondActivity.class
- .getName());
- startActivityForResult(intent, Activity.DEFAULT_KEYS_DIALER);
- }
- });
- setContentView(btn, params);
- }
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- Log.i("test", "onActivityResult is working " + resultCode);
- if (resultCode == Activity.RESULT_OK) {
- switch (requestCode) {
- case Activity.DEFAULT_KEYS_DIALER:
- Intent intent = new Intent(this, ThirdActivity.class);
- startActivityForResult(intent, Activity.DEFAULT_KEYS_DIALER + 1);
- break;
- case Activity.DEFAULT_KEYS_DIALER + 1:
- break;
- default:
- break;
- }
- }
- }
- @Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- Log.i("test", "onNewIntent is working");
- }
- }
<div id="sina_keyword_ad_area2" "="" style="color: rgb(75, 75, 75); font-family: georgia, verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20px;">
- public class SecondActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- EditText edt = new EditText(this);
- edt.setText("please input key words");
- LayoutParams params = new LayoutParams(200, 60);
- params.gravity = Gravity.CENTER;
- Button btn = new Button(this);
- btn.setText("end Second");
- params.gravity = Gravity.CENTER;
- btn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- setResult(Activity.RESULT_OK);
- finish();
- }
- });
- LinearLayout ll = new LinearLayout(this);
- ll.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.FILL_PARENT));
- ll.setOrientation(LinearLayout.VERTICAL);
- ll.addView(edt);
- ll.addView(btn);
- setContentView(ll);
-
- }
- }
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.mx.activity" android:versionCode="1" android:versionName="1.0">
- <uses-sdk android:minSdkVersion="4" />
- <application android:icon="@drawable/icon" android:label="@string/app_name"
- android:debuggable="true">
- <activity android:name=".HomeActivity" android:label="@string/app_name">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <activity android:name=".SecondActivity" android:launchMode="singleTask" />
- <activity android:name=".ThirdActivity" />
- <activity android:name="com.mx.activity.camera.CropImage" />
- </application>
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
- </manifest>
经验证:打印结果是I/test (17207): onActivityResult is working 0
0既是RESULT_CANCELED,也就是说直接取消了,onActivityResult收到RESULT_CANCELED在SecondActiviy,
启动之前,这也就说明了“if the activity you are launching”指的是被启动的activity。
再来介绍singleInstance,他和singleTask类似,不同点是singleInstance要求activity的实例不仅只有一个, 并且整个task中只有一个activity实例,而singleTask所在的栈中允许存在其他activity的实例。
由此我们可以知道设置了singleInstance的activity也具有上面的特性,此外,启动的activity设置了 singleInstance,那么无论被启动的activity有没有设置singleInstance,都无法获取返回值,可以验证一下,将 HomeActivity的android:launchMode="singleInstance"
到此,今天遇到的两个问题都明白了
第一个问题:为什么调用系统的相机程序拍照,相机程序还没有启动,onActivityResult收到RESULT_CANCELED,这是因为AccountActivity设置了singleInstance。
第二个问题:取消了AccountActivity设置了singleInstance的属性,“拍照”---》“确定”,但是却无法返回 AccountActivity,这是因为将图片存储在“/data/data/com.mx.browser/files/account.png”, 而files目录对于文件的大小有限制