Android - 方向更改后复制 "open with" 系统对话框实例
Android - duplicate "open with" system dialog instance after orientation change
我有一个简单的 activity 一键。单击按钮时,我会发出从图库中选择图像的意图。当我发出意图然后旋转屏幕时,发生了一些奇怪的事情。以下是步骤:
- 点击按钮。 "Open with" 出现系统对话框。
- 旋转屏幕。 Activity 被重新创建,对话框仍然显示。注意 - 我不会在 activity 重新创建时再次调用 startActivityForResult(Intent, int)。
- 点击后退按钮。 "Open with"对话框消失了,但是下面还有一个。
所以即使我不调用 startActivityForResult(Intent, int),每次方向改变都会创建对话框的新实例,而旧实例不会被破坏。
有人遇到这个问题吗?如何摆脱这些重复的对话框?
更新 1:
所以,这里有一些示例代码:
public class MainActivity extends AppCompatActivity
{
private boolean mIsStarted = false;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null)
{
mIsStarted = savedInstanceState.getBoolean("key");
}
if (!mIsStarted)
{
mIsStarted = true;
Intent intent = new Intent(Intent.ACTION_PICK).setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MimeType.IMAGE);
startActivityForResult(intent, 1);
}
}
@Override
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putBoolean("key", mIsStarted);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
mIsStarted = false;
}
}
我也尝试设置 android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc"
但每次旋转屏幕时,新的对话框副本(实际上这不是对话框,这是 ResolverActivity)显示在之前的对话框之上一。这是 Android 错误还是我做错了什么?
更新 2: 所以我尝试了另一种方法 - 调用 finishActivity(int) inside my Activity.onStop()
. Result is pretty strange - now I've got only 2 copies of ChooserActivity。创建第二个副本后,它开始正常旋转。
代码如下:
public class MainActivity extends AppCompatActivity
{
private static final String LOG_TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState)
{
Log.d(LOG_TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.make_photo).setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Intent intent = new Intent(Intent.ACTION_PICK).setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MimeType.IMAGE);
startActivityForResult(intent, 1);
}
});
}
@Override
protected void onStop()
{
Log.d(LOG_TAG, "onStop");
super.onStop();
finishActivity(1);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
Log.d(LOG_TAG, String.format("onActivityResult[requestCode:%d, resultCode:%d, data:%s]",
requestCode, resultCode, data != null ? data.toString() : "NULL"));
}
}
仍然想知道为什么要创建第二个副本。
将此添加到 androidmanifest.xml
中的 activity 声明中
android:configChanges="orientation|screenSize"
这将防止 activity 重新创建并解决重复对话框的问题。
发现这是我基地的愚蠢错误 Activity
class。我最终从这个基础 IntentProcessingActivity
class.
派生出所有与意图一起工作的 Activities
/**
* Base activity for all activities which process intents. This activity saves processing state
* during recreation, so derived activities can get rid of this. This is useful for not showing
* "Open with" dialogs multiple times.
* <p />
* Derived activities can check if some intent is currently processing with {@link
* #isProcessingIntent()} function.
* <p />
* Created by Maksimov Stanislav (s.maks04@gmail.com) on 25.01.16
*/
public class IntentProcessingActivity extends AppCompatActivity
{
private static final String KEY_IS_PROCESSING_INTENT = "IsProcessingIntent";
private boolean mIsProcessingIntent;
@CallSuper
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
{
mIsProcessingIntent = savedInstanceState.getBoolean(KEY_IS_PROCESSING_INTENT, false);
}
}
@CallSuper
@Override
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putBoolean(KEY_IS_PROCESSING_INTENT, mIsProcessingIntent);
}
@CallSuper
@Override
public void startActivityForResult(Intent intent, int requestCode, Bundle options)
{
mIsProcessingIntent = true;
super.startActivityForResult(intent, requestCode, options);
}
@CallSuper
@Override
public void startActivityForResult(Intent intent, int requestCode)
{
mIsProcessingIntent = true;
super.startActivityForResult(intent, requestCode);
}
@CallSuper
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
mIsProcessingIntent = false;
super.onActivityResult(requestCode, resultCode, data);
}
protected final boolean isProcessingIntent()
{
return mIsProcessingIntent;
}
}
在childActivities
我刚刚检查
if (!isProcessingIntent())
{
startActivityForResult(...);
}
我有一个简单的 activity 一键。单击按钮时,我会发出从图库中选择图像的意图。当我发出意图然后旋转屏幕时,发生了一些奇怪的事情。以下是步骤:
- 点击按钮。 "Open with" 出现系统对话框。
- 旋转屏幕。 Activity 被重新创建,对话框仍然显示。注意 - 我不会在 activity 重新创建时再次调用 startActivityForResult(Intent, int)。
- 点击后退按钮。 "Open with"对话框消失了,但是下面还有一个。
所以即使我不调用 startActivityForResult(Intent, int),每次方向改变都会创建对话框的新实例,而旧实例不会被破坏。
有人遇到这个问题吗?如何摆脱这些重复的对话框?
更新 1: 所以,这里有一些示例代码:
public class MainActivity extends AppCompatActivity
{
private boolean mIsStarted = false;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null)
{
mIsStarted = savedInstanceState.getBoolean("key");
}
if (!mIsStarted)
{
mIsStarted = true;
Intent intent = new Intent(Intent.ACTION_PICK).setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MimeType.IMAGE);
startActivityForResult(intent, 1);
}
}
@Override
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putBoolean("key", mIsStarted);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
mIsStarted = false;
}
}
我也尝试设置 android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc"
但每次旋转屏幕时,新的对话框副本(实际上这不是对话框,这是 ResolverActivity)显示在之前的对话框之上一。这是 Android 错误还是我做错了什么?
更新 2: 所以我尝试了另一种方法 - 调用 finishActivity(int) inside my Activity.onStop()
. Result is pretty strange - now I've got only 2 copies of ChooserActivity。创建第二个副本后,它开始正常旋转。
代码如下:
public class MainActivity extends AppCompatActivity
{
private static final String LOG_TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState)
{
Log.d(LOG_TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.make_photo).setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Intent intent = new Intent(Intent.ACTION_PICK).setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MimeType.IMAGE);
startActivityForResult(intent, 1);
}
});
}
@Override
protected void onStop()
{
Log.d(LOG_TAG, "onStop");
super.onStop();
finishActivity(1);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
Log.d(LOG_TAG, String.format("onActivityResult[requestCode:%d, resultCode:%d, data:%s]",
requestCode, resultCode, data != null ? data.toString() : "NULL"));
}
}
仍然想知道为什么要创建第二个副本。
将此添加到 androidmanifest.xml
android:configChanges="orientation|screenSize"
这将防止 activity 重新创建并解决重复对话框的问题。
发现这是我基地的愚蠢错误 Activity
class。我最终从这个基础 IntentProcessingActivity
class.
Activities
/**
* Base activity for all activities which process intents. This activity saves processing state
* during recreation, so derived activities can get rid of this. This is useful for not showing
* "Open with" dialogs multiple times.
* <p />
* Derived activities can check if some intent is currently processing with {@link
* #isProcessingIntent()} function.
* <p />
* Created by Maksimov Stanislav (s.maks04@gmail.com) on 25.01.16
*/
public class IntentProcessingActivity extends AppCompatActivity
{
private static final String KEY_IS_PROCESSING_INTENT = "IsProcessingIntent";
private boolean mIsProcessingIntent;
@CallSuper
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
{
mIsProcessingIntent = savedInstanceState.getBoolean(KEY_IS_PROCESSING_INTENT, false);
}
}
@CallSuper
@Override
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putBoolean(KEY_IS_PROCESSING_INTENT, mIsProcessingIntent);
}
@CallSuper
@Override
public void startActivityForResult(Intent intent, int requestCode, Bundle options)
{
mIsProcessingIntent = true;
super.startActivityForResult(intent, requestCode, options);
}
@CallSuper
@Override
public void startActivityForResult(Intent intent, int requestCode)
{
mIsProcessingIntent = true;
super.startActivityForResult(intent, requestCode);
}
@CallSuper
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
mIsProcessingIntent = false;
super.onActivityResult(requestCode, resultCode, data);
}
protected final boolean isProcessingIntent()
{
return mIsProcessingIntent;
}
}
在childActivities
我刚刚检查
if (!isProcessingIntent())
{
startActivityForResult(...);
}