package com.lsjwzh.widget.recyclerviewpager;

import java.util.HashSet;
import java.util.Set;

import android.annotation.TargetApi;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Implementation of {@link android.support.v4.view.PagerAdapter} that
 * uses a {@link android.support.v4.app.Fragment} to manage each page. This class also handles
 * saving and restoring of fragment's state.
 * <p/>
 * <p>This version of the pager is more useful when there are a large number
 * of pages, working more like a list view.  When pages are not visible to
 * the user, their entire fragment may be destroyed, only keeping the saved
 * state of that fragment.  This allows the pager to hold on to much less
 * memory associated with each visited page as compared to
 * {@link android.support.v4.app.FragmentPagerAdapter} at the cost of potentially more overhead when
 * switching between pages.
 * <p/>
 * <p>When using FragmentPagerAdapter the host ViewPager must have a
 * valid ID set.</p>
 * <p/>
 * <p>Subclasses only need to implement {@link #getItem(int, Fragment.SavedState)}
 * and {@link #getItemCount()} to have a working adapter.
 */
@TargetApi(12)
public abstract class FragmentStatePagerAdapter extends RecyclerView.Adapter<FragmentStatePagerAdapter.FragmentViewHolder> {
    private static final String TAG = "FragmentStatePagerAdapter";
    private static final boolean DEBUG = false;

    private final FragmentManager mFragmentManager;
    private FragmentTransaction mCurTransaction = null;
    SparseArray<Fragment.SavedState> mStates = new SparseArray<>();
    Set<Integer> mIds = new HashSet<>();

    public FragmentStatePagerAdapter(FragmentManager fm) {
        mFragmentManager = fm;
    }

    @Override
    public void onViewRecycled(FragmentViewHolder holder) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }
        if (DEBUG) Log.v(TAG, "Removing item #");
        int tagId = genTagId(holder.getAdapterPosition());
        Fragment f = mFragmentManager.findFragmentByTag(tagId + "");
        if (f != null) {
            if (DEBUG) Log.v(TAG, "Removing fragment #");
            mStates.put(tagId, mFragmentManager.saveFragmentInstanceState(f));
            mCurTransaction.remove(f);
            mCurTransaction.commitAllowingStateLoss();
            mCurTransaction = null;
            mFragmentManager.executePendingTransactions();
        }
        if (holder.itemView instanceof ViewGroup) {
            ((ViewGroup) holder.itemView).removeAllViews();
        }
        super.onViewRecycled(holder);
    }

    @Override
    public final FragmentViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rvp_fragment_container, parent, false);
        int id = mIds.size() + 1;
        view.findViewById(R.id.rvp_fragment_container).setId(id);
        mIds.add(id);
        return new FragmentViewHolder(view);
    }

    @Override
    public final void onBindViewHolder(final FragmentViewHolder holder, int position) {
        // do nothing
    }

    protected int genTagId(int position) {
        // itemId must not be zero
        long itemId = getItemId(position);
        if (itemId == RecyclerView.NO_ID) {
            return position + 1;
        } else {
            return (int) itemId;
        }
    }

    /**
     * Return the Fragment associated with a specified position.
     */
    public abstract Fragment getItem(int position, Fragment.SavedState savedState);

    public abstract void onDestroyItem(int position, Fragment fragment);

    public class FragmentViewHolder extends RecyclerView.ViewHolder implements View.OnAttachStateChangeListener {

        public FragmentViewHolder(View itemView) {
            super(itemView);
            itemView.addOnAttachStateChangeListener(this);
        }

        @Override
        public void onViewAttachedToWindow(View v) {
            if (mCurTransaction == null) {
                mCurTransaction = mFragmentManager.beginTransaction();
            }
            final int tagId = genTagId(getLayoutPosition());
            final Fragment fragmentInAdapter = getItem(getLayoutPosition(), mStates.get(tagId));
            if (fragmentInAdapter != null) {
                mCurTransaction.replace(itemView.getId(), fragmentInAdapter, tagId + "");
                mCurTransaction.commitAllowingStateLoss();
                mCurTransaction = null;
                mFragmentManager.executePendingTransactions();
            }
        }

        @Override
        public void onViewDetachedFromWindow(View v) {
            if (DEBUG) Log.v(TAG, "Removing fragment #");
            final int tagId = genTagId(getLayoutPosition());
            Fragment frag = mFragmentManager.findFragmentByTag(tagId + "");
            if (frag == null) {
                return;
            }
            if (mCurTransaction == null) {
                mCurTransaction = mFragmentManager.beginTransaction();
            }
            mStates.put(tagId, mFragmentManager.saveFragmentInstanceState(frag));
            mCurTransaction.remove(frag);
            mCurTransaction.commitAllowingStateLoss();
            mCurTransaction = null;
            mFragmentManager.executePendingTransactions();
            onDestroyItem(getLayoutPosition(), frag);
        }
    }
}

@@ -125,16 +125,59 @@
 getApi;%0A
+import android.support.annotation.NonNull;%0A
 import a
@@ -1465,16 +1465,237 @@
 dapter.%0A
+ * %3Cp%3EWarning:The fragment container id will be a simple sequence like %5B1,2,3....%5D;%0A * If you don't like this,you should use custom ContainerIdGenerator by  %7B@link #setContainerIdGenerator(IContainerIdGenerator)%7D%0A * %3C/p%3E%0A
  */%0A@Tar
@@ -2058,16 +2058,24 @@
 ll;%0A    
+private 
 SparseAr
@@ -2134,16 +2134,24 @@
 ();%0A    
+private 
 Set%3CInte
@@ -2183,97 +2183,493 @@
 ();%0A
-%0A    public FragmentStatePagerAdapter(FragmentManager fm) %7B%0A        mFragmentManager = fm
+    private IContainerIdGenerator mContainerIdGenerator = new IContainerIdGenerator() %7B%0A        @Override%0A        public int genId(Set%3CInteger%3E idContainer) %7B%0A            return mIds.size() + 1;%0A        %7D%0A    %7D;%0A%0A    public FragmentStatePagerAdapter(FragmentManager fm) %7B%0A        mFragmentManager = fm;%0A    %7D%0A%0A    /**%0A     * set custom idGenerator%0A     */%0A    public void setContainerIdGenerator(@NonNull IContainerIdGenerator idGenerator) %7B%0A        mContainerIdGenerator = idGenerator
 ;%0A  
@@ -3808,30 +3808,48 @@
 t id = m
-Ids.size() + 1
+ContainerIdGenerator.genId(mIds)
 ;%0A      
@@ -6371,11 +6371,108 @@
  %7D%0A    %7D
+%0A%0A    public interface IContainerIdGenerator %7B%0A        int genId(Set%3CInteger%3E idContainer);%0A    %7D
 %0A%7D%0A

add setContainerIdGenerator to generate custom container ids