Android的onActivityResult不被调用的解决方案

方案一:

现象: startActivityForResult() 后直接调用 onActivityResult()。
开发人员都知道,可以通过使用 startActivityForResult() 和 onActivityResult() 方法来传递或接收参数。
然而在一次使用中,还没等到被调用的 Activity 返回,onActivityResult() 就被执行了。
找了半于,才得知,这与 Activity 的加载模式(launchMode)有关,该属性可以在 AndroidManifest.xml 中设置。

原先将其设为 launchmode="SingleTask",经测试,所有需要传递或接收的 Activity 不允许设置该属性,或只能设为标准模式,否则系统将在 startActivityForResult() 后直接调用 onActivityResult()。

方案二:

ActivityA的代码:(放在onCreate方法中)

    Intent intent = new Intent(ActivityA.this,  ActivityB.class);  
    Bundle bundle = new Bundle();  
    bundle.putString("abc", "aaaaaaaaaaa");  
    intent.putExtra("bundle", bundle);  
    startActivityForResult(intent, RESULT_OK);

如果startActivityForResult此处写得是RESULT_OK(值为负数),则在finish到ActivityB之后,ActivityA中的onActivityResult方法不会执行。


方案三:

在Fragment中onActivityResult不被调用的解决方案(绝对管用)

常见的,我们会在FragmentActivity中嵌套一层Fragment使用,甚至Fragment下层层嵌套使用。这个时候,在第二级或者更深级别的Fragment将无法收到onActivityResult回调,查看FragementActivity的源码发现:

    public void startActivityFromFragment(Fragment fragment, Intent intent, int requestCode)
    {
        if (requestCode == -1)
        {
            super.startActivityForResult(intent, -1);
            return;
        }
                
        if ((requestCode&0xffff0000) != 0)
        {
            throw new IllegalArgumentException("Can only use lower 16 bits for requestCode");
        }
        super.startActivityForResult(intent, ((fragment.mIndex+1)<<16) + (requestCode&0xffff));
    }
            
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        mFragments.noteStateNotSaved();
        int index = requestCode>>16;
        if (index != 0)
        {
            index--;
            if (mFragments.mActive == null || index < 0 || index >= mFragments.mActive.size())
            {
                Log.w(TAG,
                    "Activity result fragment index out of range: 0x"
                        + Integer.toHexString(requestCode));
                return;
            }
            Fragment frag = mFragments.mActive.get(index);
            if (frag == null)
            {
                Log.w(TAG, "Activity result no fragment exists for index: 0x"
                    + Integer.toHexString(requestCode));
            }
            else
            {
                frag.onActivityResult(requestCode&0xffff, resultCode, data);
            }
            return;
        }
     
        super.onActivityResult(requestCode, resultCode, data);
    }


原来,程序猿偷懒,没有处理嵌套Fragment的情况,也就是说回调只到第一级Fragment,就没有继续分发。我们可以实现一个自己的FragmentActiviy,来实现继续分发,如下:

    public class BaseFragmentActiviy extends FragmentActivity
    {
        private static final String TAG = "BaseActivity";
     
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data)
        {
            FragmentManager fm = getSupportFragmentManager();
            int index = requestCode >> 16;
            if (index != 0)
            {
                index--;
                if (fm.getFragments() == null || index < 0 || index >= fm.getFragments().size())
                {
                    Log.w(TAG,
                        "Activity result fragment index out of range: 0x" +
                            Integer.toHexString(requestCode));
                    return;
                }
                Fragment frag = fm.getFragments().get(index);
                if (frag == null)
                {
                    Log.w(TAG, "Activity result no fragment exists for index: 0x" +
                        Integer.toHexString(requestCode));
                }
                else
                {
                    handleResult(frag, requestCode, resultCode, data);
                }
                return;
            }
        }
     
        /**
         * 递归调用,对所有子Fragement生效
         *
         * @param frag
         * @param requestCode
         * @param resultCode
         * @param data
         */
        private void handleResult(Fragment frag, int requestCode, int resultCode, Intent data)
        {
            frag.onActivityResult(requestCode & 0xffff, resultCode, data);
            List<Fragment> frags = frag.getChildFragmentManager().getFragments();
            if (frags != null)
            {
                for (Fragment f : frags)
                {
                    if (f != null)
                        handleResult(f, requestCode, resultCode, data);
                }
            }
        }


然后我们继承这个BaseFragmentActivity即可,但是要注意,在Fragment中启动Activity时,一定要调用根Fragment的启动方法,如下:

    /**
     * 得到根Fragment
     *
     * @return
     */
    private Fragment getRootFragment()
    {
        Fragment fragment = getParentFragment();
        while (fragment.getParentFragment() != null)
        {
            fragment = fragment.getParentFragment();
        }
        return fragment;
    }
     
    /**
     * 启动Activity
     */
    private void onClickTextViewRemindAdvancetime()
    {
        Intent intent = new Intent();
        intent.setClass(getActivity(), YourActivity.class);
        intent.putExtra("TAG","TEST");
        getRootFragment().startActivityForResult(intent, 1001);
    }
 

方案四

如果在代码中用了databing,即ViewModel。如果在ViewModel实现跳转,也将导致无法回调onActivityResult。直接把跳转放到Activity或Fragment中即可