嵌套Support Fragment无法接收onActivityResult回调的解决方案

事情的原因先浏览下这里.

其中主要回复:

Sorry, the support library can't do the same thing as the platform, because it has to run on older versions of the platform that don't support fragments, only having the integer request code. Over time, moving to the platform implementation of fragments is the solution to this.

如果界面的设计如下:

Activity/
        Fragment/
                Fragment

因为兼容包的问题,我们无法接收到onActivityResult方法的回调,并且StackOverFlow里面的一些解决方法因为或多或少都有点问题,所以自己选了个折中的方案,制作了一个ChildFragmentEvent帮助Child Fragment来利用Parent Fragment来启动

Create ChildFragmentEvent

package im.youji.app.utils;

import android.content.Intent;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.util.SparseArray;

/**
 * Created by solo on 14/10/1.
 */
public class ChildFragmentEvent {

    private final Fragment parentFragment;
    private SparseArray childFragments;

    public static interface IStartActivityBehavior {
        void startActivityForResult(Intent intent, int requestCode, Fragment fragment);
    }

    public ChildFragmentEvent(Fragment parentFragment, Bundle savedInstanceState) {
        this.parentFragment = parentFragment;
        if (savedInstanceState != null) {
            childFragments = savedInstanceState.getSparseParcelableArray("childFragments");
        } else {
            childFragments = new SparseArray<>();
        }
    }

    public void onSaveInstanceState(Bundle outState) {
        outState.putSparseParcelableArray("childFragments", childFragments);
    }

    public int register(int requestCode, Fragment fragment) {
        int parentRequestCode = childFragments.size() + 1;
        childFragments.put(parentRequestCode, new ChildFragmentItem(requestCode, fragment.getId(), fragment.getTag()));
        return parentRequestCode;
    }

    public void dispatch(int parentRequestCode, int resultCode, Intent data) {
        ChildFragmentItem item = childFragments.get(parentRequestCode);
        if (item == null) {
            return;
        }
        Fragment fragment = null;
        if (item.getId() != null) {
            fragment = parentFragment.getChildFragmentManager().findFragmentById(item.getId());
        } else if (item.getTag() != null) {
            fragment = parentFragment.getChildFragmentManager().findFragmentByTag(item.getTag());
        }
        if (fragment != null) {
            fragment.onActivityResult(item.getRequestCode(), resultCode, data);
        }
    }

    private static class ChildFragmentItem implements Parcelable {
        int requestCode;
        Integer id;
        String tag;

        public ChildFragmentItem(int requestCode, int id, String tag) {
            this.requestCode = requestCode;
            this.id = id;
            this.tag = tag;
        }

        public int getRequestCode() {
            return requestCode;
        }

        public Integer getId() {
            return id;
        }

        public String getTag() {
            return tag;
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(this.requestCode);
            dest.writeValue(this.id);
            dest.writeString(this.tag);
        }

        private ChildFragmentItem(Parcel in) {
            this.requestCode = in.readInt();
            this.id = (Integer) in.readValue(Integer.class.getClassLoader());
            this.tag = in.readString();
        }

        public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
            public ChildFragmentItem createFromParcel(Parcel source) {
                return new ChildFragmentItem(source);
            }

            public ChildFragmentItem[] newArray(int size) {
                return new ChildFragmentItem[size];
            }
        };
    }

}

How to use

Parent Fragment

import android.support.v4.app.Fragment;

public class EventGroupFragment extends Fragment implements ChildFragmentEvent.IStartActivityBehavior {
    private ChildFragmentEvent childFragmentEvent;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        childFragmentEvent = new ChildFragmentEvent(this, savedInstanceState);
    }
    @Override
    public void onSaveInstanceState(Bundle outState) {
       childFragmentEvent.onSaveInstanceState(outState);
    }
    @Override
    public void startActivityForResult(Intent intent, int requestCode, Fragment fragment) {
        // get the parent requestCode after register
        super.startActivityForResult(intent, childFragmentEvent.register(requestCode, fragment));
    }
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        // dispatch to child fragments
        childFragmentEvent.dispatch(requestCode, resultCode, data);
    }
}

Child Fragment

// Use this code to startActivity
((ChildFragmentEvent.IStartActivityBehavior) getParentFragment())
                .startActivityForResult(intent, REQUEST_SIMPLE, this);
                
// Get Result
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case REQUEST_SIMPLE:
            // do something
            break;
    }
}

End

最后,如果项目设计过于复杂,使用上面这种折中方法也会导致混乱,比如嵌套Fragment过多,需要明确知道哪个ParentFragment能够正确处理启动StartActivity。

转载请附上本文地址

你可能感兴趣的:(嵌套Support Fragment无法接收onActivityResult回调的解决方案)