Android - 方向更改后复制 "open with" 系统对话框实例

Android - duplicate "open with" system dialog instance after orientation change

我有一个简单的 activity 一键。单击按钮时,我会发出从图库中选择图像的意图。当我发出意图然后旋转屏幕时,发生了一些奇怪的事情。以下是步骤:

  1. 点击按钮。 "Open with" 出现系统对话框。
  2. 旋转屏幕。 Activity 被重新创建,对话框仍然显示。注意 - 我不会在 activity 重新创建时再次调用 startActivityForResult(Intent, int)。
  3. 点击后退按钮。 "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(...);
}