Android - 重复"打开"方向改变后的系统对话框实例

时间:2016-01-22 15:41:28

标签: android android-intent orientation-changes

我只用一个按钮即可完成简单的活动。单击按钮时,我会触发从图库中选择图像的意图。当我触发意图然后旋转屏幕时,会发生一些奇怪的事情。以下是步骤:

  1. 点击按钮。 "打开"出现系统对话框。
  2. 旋转屏幕。重新创建活动,仍然显示对话框。注意 - 我在重新创建活动时不会再次调用startActivityForResult(Intent,int)。
  3. 点按后退按钮。 "打开"对话框消失了,但是下面还有另一个。
  4. 所以即使我没有调用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:所以我尝试了另一种方法 - 在Activity.onStop()内调用finishActivity(int)。结果很奇怪 - 现在我只有2份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"));
        }
    }
    

    仍然想知道为什么要制作第二份副本。

2 个答案:

答案 0 :(得分:0)

将此添加到androidmanifest.xml

中的活动声明中
android:configChanges="orientation|screenSize"

这将阻止重新创建活动并解决重复对话的问题。

答案 1 :(得分:0)

在基础Activity课程中发现这是一个愚蠢的错误。我最终导出了所有与Activities类基础中的意图一起使用的IntentProcessingActivity

/**
 * 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;
    }
}

在孩子Activities上,我只需检查

if (!isProcessingIntent())
{
    startActivityForResult(...);
}