Java 在新的嵌套片段API中未调用onActivityResult()

Java 在新的嵌套片段API中未调用onActivityResult(),java,android,kotlin,android-fragments,android-nested-fragment,Java,Android,Kotlin,Android Fragments,Android Nested Fragment,我一直在使用Android支持库中包含的新API 对于嵌套片段,我面临的问题是,如果一个嵌套片段(即通过getChildFragmentManager()返回的FragmentManager添加到另一个片段的片段)调用startActivityForResult(),则嵌套片段的onActivityResult()方法未被调用。但是,父片段的onActivityResult()和活动的onActivityResult()都会被调用 我不知道我是否遗漏了嵌套片段的某些内容,但我没有预料到所描述的行

我一直在使用Android支持库中包含的新API

对于嵌套片段,我面临的问题是,如果一个嵌套片段(即通过
getChildFragmentManager()
返回的
FragmentManager
添加到另一个片段的片段)调用
startActivityForResult()
,则嵌套片段的
onActivityResult()
方法未被调用。但是,父片段的
onActivityResult()
和活动的
onActivityResult()
都会被调用

我不知道我是否遗漏了嵌套片段的某些内容,但我没有预料到所描述的行为。下面是重现此问题的代码。如果有人能给我指出正确的方向并向我解释我做错了什么,我将不胜感激:

package com.example.nestedfragmentactivityresult;
导入android.media.ringtonemager;
导入android.os.Bundle;
导入android.content.Intent;
导入android.support.v4.app.Fragment;
导入android.support.v4.app.FragmentActivity;
导入android.view.LayoutInflater;
导入android.view.view;
导入android.view.ViewGroup;
导入android.widget.Button;
导入android.widget.Toast;
公共类MainActivity扩展了FragmentActivity
{
创建时的公共void(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
此文件名为.getSupportFragmentManager()
.beginTransaction()
.add(android.R.id.content,新的ContainerFragment())
.commit();
}
ActivityResult上的公共void(int请求代码、int结果代码、意图数据)
{
super.onActivityResult(请求代码、结果代码、数据);
//这叫做
Toast.makeText(getApplication(),
“被活动消耗”,
吐司。长度(短)。show();
}
公共静态类ContainerFragment扩展了片段
{
创建视图上的公共最终视图(更平坦的充气机,
视图组容器,
Bundle savedInstanceState)
{
查看结果=充气机。充气(R.layout.test\u嵌套的\u碎片\u容器,
集装箱,
假);
返回结果;
}
已创建ActivityState上的公共无效(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
getChildFragmentManager().beginTransaction()
.add(R.id.content,new NestedFragment())
.commit();
}
ActivityResult上的公共无效(int请求代码,
int结果代码,
意图(数据)
{
super.onActivityResult(请求代码、结果代码、数据);
//这叫做
Toast.makeText(getActivity(),
“被父片段消耗”,
吐司。长度(短)。show();
}
}
公共静态类NestedFragment扩展了片段
{
创建视图上的公共最终视图(更平坦的充气机,
视图组容器,
Bundle savedInstanceState)
{
按钮按钮=新按钮(getActivity());
button.setText(“单击我!”);
setOnClickListener(新视图.OnClickListener()
{
公共void onClick(视图v)
{
意向意向=新意向(铃声管理器.操作\u铃声\u选择器);
startActivityForResult(意向,0);
}
});
返回按钮;
}
ActivityResult上的公共无效(int请求代码,
int结果代码,
意图(数据)
{
super.onActivityResult(请求代码、结果代码、数据);
//这不叫
Toast.makeText(getActivity(),
“被嵌套片段消耗”,
吐司。长度(短)。show();
}
}
}
test_nested_fragment_container.xml是:


是的,嵌套片段中的
onActivityResult()
将不会以这种方式调用

onActivityResult(在Android支持库中)的调用顺序为

  • Activity.dispatchActivityResult()
  • FragmentActivity.onActivityResult()
  • Fragment.onActivityResult()
    在第三步中,在父级
    活动
    碎片管理器
    中找到碎片。因此,在您的示例中,发现在ActivityResult()上分派
    的是容器片段,嵌套片段永远无法接收事件


    我认为您必须在ContainerFragment.onActivityResult()中实现自己的分派,找到嵌套的片段并调用它,然后将结果和数据传递给它。

    下面是我如何解决它的

    在活动中:

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        List<Fragment> frags = getSupportFragmentManager().getFragments();
        if (frags != null) {
            for (Fragment f : frags) {
                if (f != null)
                    handleResult(f, requestCode, resultCode, data);
            }
        }
    }
    
    private void handleResult(Fragment frag, int requestCode, int resultCode, Intent data) {
        if (frag instanceof IHandleActivityResult) { // custom interface with no signitures
            frag.onActivityResult(requestCode, resultCode, data);
        }
        List<Fragment> frags = frag.getChildFragmentManager().getFragments();
        if (frags != null) {
            for (Fragment f : frags) {
                if (f != null)
                    handleResult(f, requestCode, resultCode, data);
            }
        }
    }
    
    @覆盖
    受保护的void onActivityResult(int请求代码、int结果代码、意图数据){
    super.onActivityResult(请求代码、结果代码、数据);
    List frags=getSupportFragmentManager().getFragments();
    if(frags!=null){
    用于(碎片f:碎片){
    如果(f!=null)
    HandlerResult(f、请求代码、结果代码、数据);
    }
    }
    }
    私有void handleResult(片段片段、int请求代码、int结果代码、意图数据){
    if(IHandleActivityResult的frag实例){//无符号的自定义接口
    frag.onActivityResult(请求代码、结果代码、数据);
    }
    List frags=frag.getChildFragmentManager().getFragments();
    if(frags!=null){
    用于(碎片f:碎片){
    如果(f!=null)
    HandlerResult(f、请求代码、结果代码、数据);
    }
    }
    }
    
    我也面临同样的问题!我
    private static ChildFragment mChildFragment;
    
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    
        mChildFragment.onActivityResult(int requestCode, int resultCode, Intent data);
    
    }
    
    @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
    
            List<Fragment> fragments = getChildFragmentManager().getFragments();
            if (fragments != null) {
                for (Fragment fragment : fragments) {
                    fragment.onActivityResult(requestCode, resultCode, data);
                }
            }
        }
    
    getParentFragment().startActivityForResult(intent, requestCode);
    
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        val navHostFragment = supportFragmentManager.findFragmentById(R.id.your_nav_host_fragment)
        val childFragments = navHostFragment?.childFragmentManager?.fragments
        childFragments?.forEach { it.onActivityResult(requestCode, resultCode, data) }
    }
    
      @Override
    public void onActivityResult(int requestCode, int resultCode, Intent result) {
        super.onActivityResult(requestCode, resultCode, result);
        if (requestCode == Crop.REQUEST_PICK && resultCode == RESULT_OK) {
            beginCrop(result.getData());
        } }
    
     Intent pickContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts"));
            pickContactIntent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE); // Show user only contacts w/ phone numbers
           startActivityForResult(pickContactIntent, 103);
    
       @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == 101 && resultCode == getActivity().RESULT_OK && null != data) {
    
    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--;
            final int activeFragmentsCount = mFragments.getActiveFragmentsCount();
            if (activeFragmentsCount == 0 || index < 0 || index >= activeFragmentsCount) {
                Log.w(TAG, "Activity result fragment index out of range: 0x"
                        + Integer.toHexString(requestCode));
                return;
            }
            final List<Fragment> activeFragments =
                    mFragments.getActiveFragments(new ArrayList<Fragment>(activeFragmentsCount));
            Fragment frag = activeFragments.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);
    }
    
    public abstract class NestedFragment extends Fragment {
    
    @Override
    public void startActivityForResult(Intent intent, int requestCode) {
    
        List<Fragment> fragments = getFragmentManager().getFragments();
        int index = fragments.indexOf(this);
        if (index >= 0) {
            if (getParentFragment() != null) {
                requestCode = ((index + 1) << 8) + requestCode;
                getParentFragment().startActivityForResult(intent, requestCode);
            } else {
                super.startActivityForResult(intent, requestCode);
            }
    
        }
    }
    
    public abstract class MyFragment extends Fragment {
    
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        int index = requestCode >> 8;
        if (index > 0) {
            //from nested fragment
            index--;
    
            List<Fragment> fragments = getChildFragmentManager().getFragments();
            if (fragments != null && fragments.size() > index) {
                fragments.get(index).onActivityResult(requestCode & 0x00ff, resultCode, data);
            }
        }
    }