public class IRecyclerView extends RecyclerView {
    private static final String TAG = IRecyclerView.class.getSimpleName();

    private static final int STATUS_DEFAULT = 0;

    private static final int STATUS_SWIPING_TO_REFRESH = 1;

    private static final int STATUS_RELEASE_TO_REFRESH = 2;

    private static final int STATUS_REFRESHING = 3;

    private static final boolean DEBUG = false;

    private int mStatus;

    private boolean mIsAutoRefreshing;

    private boolean mRefreshEnabled;

    private boolean mLoadMoreEnabled;

    private int mRefreshFinalMoveOffset;

    private OnRefreshListener mOnRefreshListener;

    private OnLoadMoreListener mOnLoadMoreListener;

    private RefreshHeaderLayout mRefreshHeaderContainer;

    private FrameLayout mLoadMoreFooterContainer;

    private LinearLayout mHeaderViewContainer;

    private LinearLayout mFooterViewContainer;

    private View mRefreshHeaderView;

    private View mLoadMoreFooterView;

    public IRecyclerView(Context context) {
        this(context, null);
    }

    public IRecyclerView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public IRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.IRecyclerView, defStyle, 0);
        @LayoutRes int refreshHeaderLayoutRes = -1;
        @LayoutRes int loadMoreFooterLayoutRes = -1;
        int refreshFinalMoveOffset = -1;
        boolean refreshEnabled;
        boolean loadMoreEnabled;

        try {
            refreshEnabled = a.getBoolean(R.styleable.IRecyclerView_refreshEnabled, false);
            loadMoreEnabled = a.getBoolean(R.styleable.IRecyclerView_loadMoreEnabled, false);
            refreshHeaderLayoutRes = a.getResourceId(R.styleable.IRecyclerView_refreshHeaderLayout, -1);
            loadMoreFooterLayoutRes = a.getResourceId(R.styleable.IRecyclerView_loadMoreFooterLayout, -1);
            refreshFinalMoveOffset = a.getDimensionPixelOffset(R.styleable.IRecyclerView_refreshFinalMoveOffset, -1);
        } finally {
            a.recycle();
        }

        setRefreshEnabled(refreshEnabled);

        setLoadMoreEnabled(loadMoreEnabled);

        if (refreshHeaderLayoutRes != -1) {
            setRefreshHeaderView(refreshHeaderLayoutRes);
        }
        if (loadMoreFooterLayoutRes != -1) {
            setLoadMoreFooterView(loadMoreFooterLayoutRes);
        }
        if (refreshFinalMoveOffset != -1) {
            setRefreshFinalMoveOffset(refreshFinalMoveOffset);
        }
        setStatus(STATUS_DEFAULT);
    }

    @Override
    protected void onMeasure(int widthSpec, int heightSpec) {
        super.onMeasure(widthSpec, heightSpec);
        if (mRefreshHeaderView != null) {
            if (mRefreshHeaderView.getMeasuredHeight() > mRefreshFinalMoveOffset) {
                mRefreshFinalMoveOffset = 0;
            }
        }
    }

    public void setRefreshEnabled(boolean enabled) {
        this.mRefreshEnabled = enabled;
    }

    public void setLoadMoreEnabled(boolean enabled) {
        this.mLoadMoreEnabled = enabled;
        if (mLoadMoreEnabled) {
            removeOnScrollListener(mOnLoadMoreScrollListener);
            addOnScrollListener(mOnLoadMoreScrollListener);
        } else {
            removeOnScrollListener(mOnLoadMoreScrollListener);
        }
    }

    public void setOnRefreshListener(OnRefreshListener listener) {
        this.mOnRefreshListener = listener;
    }

    public void setOnLoadMoreListener(OnLoadMoreListener listener) {
        this.mOnLoadMoreListener = listener;
    }

    public void setRefreshing(boolean refreshing) {
        if (mStatus == STATUS_DEFAULT && refreshing) {
            this.mIsAutoRefreshing = true;
            setStatus(STATUS_SWIPING_TO_REFRESH);
            startScrollDefaultStatusToRefreshingStatus();
        } else if (mStatus == STATUS_REFRESHING && !refreshing) {
            this.mIsAutoRefreshing = false;
            startScrollRefreshingStatusToDefaultStatus();
        } else {
            this.mIsAutoRefreshing = false;
            Log.w(TAG, "isRefresh = " + refreshing + " current status = " + mStatus);
        }
    }

    public void setRefreshFinalMoveOffset(int refreshFinalMoveOffset) {
        this.mRefreshFinalMoveOffset = refreshFinalMoveOffset;
    }

    public void setRefreshHeaderView(View refreshHeaderView) {
        if (!(refreshHeaderView instanceof RefreshTrigger)) {
            throw new ClassCastException("Refresh header view must be an implement of RefreshTrigger");
        }

        if (mRefreshHeaderView != null) {
            removeRefreshHeaderView();
        }
        if (mRefreshHeaderView != refreshHeaderView) {
            this.mRefreshHeaderView = refreshHeaderView;
            ensureRefreshHeaderContainer();
            mRefreshHeaderContainer.addView(refreshHeaderView);
        }
    }

    public void setRefreshHeaderView(@LayoutRes int refreshHeaderLayoutRes) {
        ensureRefreshHeaderContainer();
        final View refreshHeader = LayoutInflater.from(getContext()).inflate(refreshHeaderLayoutRes, mRefreshHeaderContainer, false);
        if (refreshHeader != null) {
            setRefreshHeaderView(refreshHeader);
        }
    }

    public void setLoadMoreFooterView(View loadMoreFooterView) {
        if (mLoadMoreFooterView != null) {
            removeLoadMoreFooterView();
        }
        if (mLoadMoreFooterView != loadMoreFooterView) {
            this.mLoadMoreFooterView = loadMoreFooterView;
            ensureLoadMoreFooterContainer();
            mLoadMoreFooterContainer.addView(loadMoreFooterView);
        }
    }

    public void setLoadMoreFooterView(@LayoutRes int loadMoreFooterLayoutRes) {
        ensureLoadMoreFooterContainer();
        final View loadMoreFooter = LayoutInflater.from(getContext()).inflate(loadMoreFooterLayoutRes, mLoadMoreFooterContainer, false);
        if (loadMoreFooter != null) {
            setLoadMoreFooterView(loadMoreFooter);
        }
    }

    public View getRefreshHeaderView() {
        return mRefreshHeaderView;
    }

    public View getLoadMoreFooterView() {
        return mLoadMoreFooterView;
    }

    public LinearLayout getHeaderContainer() {
        ensureHeaderViewContainer();
        return mHeaderViewContainer;
    }

    public LinearLayout getFooterContainer() {
        ensureFooterViewContainer();
        return mFooterViewContainer;
    }

    public void addHeaderView(View headerView) {
        ensureHeaderViewContainer();
        mHeaderViewContainer.addView(headerView);
        Adapter adapter = getAdapter();
        if (adapter != null) {
            adapter.notifyItemChanged(1);
        }
    }

    public void addFooterView(View footerView) {
        ensureFooterViewContainer();
        mFooterViewContainer.addView(footerView);
        Adapter adapter = getAdapter();
        if (adapter != null) {
            adapter.notifyItemChanged(adapter.getItemCount() - 2);
        }
    }

    public RecyclerView.Adapter getIAdapter() {
        final WrapperAdapter wrapperAdapter = (WrapperAdapter) getAdapter();
        return wrapperAdapter.getAdapter();
    }

    public void setIAdapter(Adapter adapter) {
        ensureRefreshHeaderContainer();
        ensureHeaderViewContainer();
        ensureFooterViewContainer();
        ensureLoadMoreFooterContainer();
        setAdapter(new WrapperAdapter(adapter, mRefreshHeaderContainer, mHeaderViewContainer, mFooterViewContainer, mLoadMoreFooterContainer));
    }

    private void ensureRefreshHeaderContainer() {
        if (mRefreshHeaderContainer == null) {
            mRefreshHeaderContainer = new RefreshHeaderLayout(getContext());
            mRefreshHeaderContainer.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0));
        }
    }

    private void ensureLoadMoreFooterContainer() {
        if (mLoadMoreFooterContainer == null) {
            mLoadMoreFooterContainer = new FrameLayout(getContext());
            mLoadMoreFooterContainer.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        }
    }

    private void ensureHeaderViewContainer() {
        if (mHeaderViewContainer == null) {
            mHeaderViewContainer = new LinearLayout(getContext());
            mHeaderViewContainer.setOrientation(LinearLayout.VERTICAL);
            mHeaderViewContainer.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        }
    }

    private void ensureFooterViewContainer() {
        if (mFooterViewContainer == null) {
            mFooterViewContainer = new LinearLayout(getContext());
            mFooterViewContainer.setOrientation(LinearLayout.VERTICAL);
            mFooterViewContainer.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        }
    }

    private void removeRefreshHeaderView() {
        if (mRefreshHeaderContainer != null) {
            mRefreshHeaderContainer.removeView(mRefreshHeaderView);
        }
    }

    private void removeLoadMoreFooterView() {
        if (mLoadMoreFooterContainer != null) {
            mLoadMoreFooterContainer.removeView(mLoadMoreFooterView);
        }
    }

    private int mActivePointerId = -1;
    private int mLastTouchX = 0;
    private int mLastTouchY = 0;

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        final int action = MotionEventCompat.getActionMasked(e);
        final int actionIndex = MotionEventCompat.getActionIndex(e);
        switch (action) {
            case MotionEvent.ACTION_DOWN: {
                mActivePointerId = MotionEventCompat.getPointerId(e, 0);
                mLastTouchX = (int) (MotionEventCompat.getX(e, actionIndex) + 0.5f);
                mLastTouchY = (int) (MotionEventCompat.getY(e, actionIndex) + 0.5f);
            }
            break;

            case MotionEvent.ACTION_POINTER_DOWN: {
                mActivePointerId = MotionEventCompat.getPointerId(e, actionIndex);
                mLastTouchX = (int) (MotionEventCompat.getX(e, actionIndex) + 0.5f);
                mLastTouchY = (int) (MotionEventCompat.getY(e, actionIndex) + 0.5f);
            }
            break;

            case MotionEventCompat.ACTION_POINTER_UP: {
                onPointerUp(e);
            }
            break;
        }

        return super.onInterceptTouchEvent(e);
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        final int action = MotionEventCompat.getActionMasked(e);
        switch (action) {
            case MotionEvent.ACTION_DOWN: {
                final int index = MotionEventCompat.getActionIndex(e);
                mActivePointerId = MotionEventCompat.getPointerId(e, 0);
                mLastTouchX = getMotionEventX(e, index);
                mLastTouchY = getMotionEventY(e, index);
            }
            break;

            case MotionEvent.ACTION_MOVE: {
                final int index = MotionEventCompat.findPointerIndex(e, mActivePointerId);
                if (index < 0) {
                    Log.e(TAG, "Error processing scroll; pointer index for id " + index + " not found. Did any MotionEvents get skipped?");
                    return false;
                }

                final int x = getMotionEventX(e, index);
                final int y = getMotionEventY(e, index);

                final int dx = x - mLastTouchX;
                final int dy = y - mLastTouchY;

                mLastTouchX = x;
                mLastTouchY = y;

                final boolean triggerCondition = isEnabled() && mRefreshEnabled && mRefreshHeaderView != null && isFingerDragging() && canTriggerRefresh();
                if (DEBUG) {
                    Log.i(TAG, "triggerCondition = " + triggerCondition + "; mStatus = " + mStatus + "; dy = " + dy);
                }
                if (triggerCondition) {

                    final int refreshHeaderContainerHeight = mRefreshHeaderContainer.getMeasuredHeight();
                    final int refreshHeaderViewHeight = mRefreshHeaderView.getMeasuredHeight();

                    if (dy > 0 && mStatus == STATUS_DEFAULT) {
                        setStatus(STATUS_SWIPING_TO_REFRESH);
                        mRefreshTrigger.onStart(false, refreshHeaderViewHeight, mRefreshFinalMoveOffset);
                    } else if (dy < 0) {
                        if (mStatus == STATUS_SWIPING_TO_REFRESH && refreshHeaderContainerHeight <= 0) {
                            setStatus(STATUS_DEFAULT);
                        }
                        if (mStatus == STATUS_DEFAULT) {
                            break;
                        }
                    }

                    if (mStatus == STATUS_SWIPING_TO_REFRESH || mStatus == STATUS_RELEASE_TO_REFRESH) {
                        if (refreshHeaderContainerHeight >= refreshHeaderViewHeight) {
                            setStatus(STATUS_RELEASE_TO_REFRESH);
                        } else {
                            setStatus(STATUS_SWIPING_TO_REFRESH);
                        }
                        fingerMove(dy);
                        return true;
                    }
                }
            }
            break;

            case MotionEventCompat.ACTION_POINTER_DOWN: {
                final int index = MotionEventCompat.getActionIndex(e);
                mActivePointerId = MotionEventCompat.getPointerId(e, index);
                mLastTouchX = getMotionEventX(e, index);
                mLastTouchY = getMotionEventY(e, index);
            }
            break;

            case MotionEventCompat.ACTION_POINTER_UP: {
                onPointerUp(e);
            }
            break;

            case MotionEvent.ACTION_UP: {
                onFingerUpStartAnimating();
            }
            break;

            case MotionEvent.ACTION_CANCEL: {
                onFingerUpStartAnimating();
            }
            break;
        }
        return super.onTouchEvent(e);
    }

    private boolean isFingerDragging() {
        return getScrollState() == SCROLL_STATE_DRAGGING;
    }

    public boolean canTriggerRefresh() {
        final Adapter adapter = getAdapter();
        if (adapter == null || adapter.getItemCount() <= 0) {
            return true;
        }
        View firstChild = getChildAt(0);
        int position = getChildLayoutPosition(firstChild);
        if (position == 0) {
            if (firstChild.getTop() == mRefreshHeaderContainer.getTop()) {
                return true;
            }
        }
        return false;
    }

    private int getMotionEventX(MotionEvent e, int pointerIndex) {
        return (int) (MotionEventCompat.getX(e, pointerIndex) + 0.5f);
    }

    private int getMotionEventY(MotionEvent e, int pointerIndex) {
        return (int) (MotionEventCompat.getY(e, pointerIndex) + 0.5f);
    }

    private void onFingerUpStartAnimating() {
        if (mStatus == STATUS_RELEASE_TO_REFRESH) {
            startScrollReleaseStatusToRefreshingStatus();
        } else if (mStatus == STATUS_SWIPING_TO_REFRESH) {
            startScrollSwipingToRefreshStatusToDefaultStatus();
        }
    }

    private void onPointerUp(MotionEvent e) {
        final int actionIndex = MotionEventCompat.getActionIndex(e);
        if (MotionEventCompat.getPointerId(e, actionIndex) == mActivePointerId) {
            // Pick a new pointer to pick up the slack.
            final int newIndex = actionIndex == 0 ? 1 : 0;
            mActivePointerId = MotionEventCompat.getPointerId(e, newIndex);
            mLastTouchX = getMotionEventX(e, newIndex);
            mLastTouchY = getMotionEventY(e, newIndex);
        }
    }

    private void fingerMove(int dy) {
        int ratioDy = (int) (dy * 0.5f + 0.5f);
        int offset = mRefreshHeaderContainer.getMeasuredHeight();
        int finalDragOffset = mRefreshFinalMoveOffset;

        int nextOffset = offset + ratioDy;
        if (finalDragOffset > 0) {
            if (nextOffset > finalDragOffset) {
                ratioDy = finalDragOffset - offset;
            }
        }

        if (nextOffset < 0) {
            ratioDy = -offset;
        }
        move(ratioDy);
    }

    private void move(int dy) {
        if (dy != 0) {
            int height = mRefreshHeaderContainer.getMeasuredHeight() + dy;
            setRefreshHeaderContainerHeight(height);
            mRefreshTrigger.onMove(false, false, height);
        }
    }

    private void setRefreshHeaderContainerHeight(int height) {
        mRefreshHeaderContainer.getLayoutParams().height = height;
        mRefreshHeaderContainer.requestLayout();
    }

    private void startScrollDefaultStatusToRefreshingStatus() {
        mRefreshTrigger.onStart(true, mRefreshHeaderView.getMeasuredHeight(), mRefreshFinalMoveOffset);

        int targetHeight = mRefreshHeaderView.getMeasuredHeight();
        int currentHeight = mRefreshHeaderContainer.getMeasuredHeight();
        startScrollAnimation(400, new AccelerateInterpolator(), currentHeight, targetHeight);
    }

    private void startScrollSwipingToRefreshStatusToDefaultStatus() {
        final int targetHeight = 0;
        final int currentHeight = mRefreshHeaderContainer.getMeasuredHeight();
        startScrollAnimation(300, new DecelerateInterpolator(), currentHeight, targetHeight);
    }

    private void startScrollReleaseStatusToRefreshingStatus() {
        mRefreshTrigger.onRelease();

        final int targetHeight = mRefreshHeaderView.getMeasuredHeight();
        final int currentHeight = mRefreshHeaderContainer.getMeasuredHeight();
        startScrollAnimation(300, new DecelerateInterpolator(), currentHeight, targetHeight);
    }

    private void startScrollRefreshingStatusToDefaultStatus() {
        mRefreshTrigger.onComplete();

        final int targetHeight = 0;
        final int currentHeight = mRefreshHeaderContainer.getMeasuredHeight();
        startScrollAnimation(400, new DecelerateInterpolator(), currentHeight, targetHeight);
    }

    private ValueAnimator mScrollAnimator;

    private void startScrollAnimation(final int time, final Interpolator interpolator, int value, int toValue) {
        if (mScrollAnimator == null) {
            mScrollAnimator = new ValueAnimator();
        }
        //cancel
        mScrollAnimator.removeAllUpdateListeners();
        mScrollAnimator.removeAllListeners();
        mScrollAnimator.cancel();

        //reset new value
        mScrollAnimator.setIntValues(value, toValue);
        mScrollAnimator.setDuration(time);
        mScrollAnimator.setInterpolator(interpolator);
        mScrollAnimator.addUpdateListener(mAnimatorUpdateListener);
        mScrollAnimator.addListener(mAnimationListener);
        mScrollAnimator.start();
    }

    private ValueAnimator.AnimatorUpdateListener mAnimatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            final int height = (Integer) animation.getAnimatedValue();
            setRefreshHeaderContainerHeight(height);
            switch (mStatus) {
                case STATUS_SWIPING_TO_REFRESH: {
                    mRefreshTrigger.onMove(false, true, height);
                }
                break;

                case STATUS_RELEASE_TO_REFRESH: {
                    mRefreshTrigger.onMove(false, true, height);
                }
                break;

                case STATUS_REFRESHING: {
                    mRefreshTrigger.onMove(true, true, height);
                }
                break;
            }

        }
    };

    private Animator.AnimatorListener mAnimationListener = new SimpleAnimatorListener() {
        @Override
        public void onAnimationEnd(Animator animation) {
            int lastStatus = mStatus;

            switch (mStatus) {
                case STATUS_SWIPING_TO_REFRESH: {
                    if (mIsAutoRefreshing) {
                        mRefreshHeaderContainer.getLayoutParams().height = mRefreshHeaderView.getMeasuredHeight();
                        mRefreshHeaderContainer.requestLayout();
                        setStatus(STATUS_REFRESHING);
                        if (mOnRefreshListener != null) {
                            mOnRefreshListener.onRefresh();
                            mRefreshTrigger.onRefresh();
                        }
                    } else {
                        mRefreshHeaderContainer.getLayoutParams().height = 0;
                        mRefreshHeaderContainer.requestLayout();
                        setStatus(STATUS_DEFAULT);
                    }
                }
                break;

                case STATUS_RELEASE_TO_REFRESH: {
                    mRefreshHeaderContainer.getLayoutParams().height = mRefreshHeaderView.getMeasuredHeight();
                    mRefreshHeaderContainer.requestLayout();
                    setStatus(STATUS_REFRESHING);
                    if (mOnRefreshListener != null) {
                        mOnRefreshListener.onRefresh();
                        mRefreshTrigger.onRefresh();
                    }
                }
                break;

                case STATUS_REFRESHING: {
                    mIsAutoRefreshing = false;
                    mRefreshHeaderContainer.getLayoutParams().height = 0;
                    mRefreshHeaderContainer.requestLayout();
                    setStatus(STATUS_DEFAULT);
                    mRefreshTrigger.onReset();
                }
                break;
            }
            if (DEBUG) {
                Log.i(TAG, "onAnimationEnd " + getStatusLog(lastStatus) + " -> " + getStatusLog(mStatus) + " ;refresh view height:" + mRefreshHeaderContainer.getMeasuredHeight());
            }
        }
    };

    private RefreshTrigger mRefreshTrigger = new RefreshTrigger() {
        @Override
        public void onStart(boolean automatic, int headerHeight, int finalHeight) {
            if (mRefreshHeaderView != null && mRefreshHeaderView instanceof RefreshTrigger) {
                RefreshTrigger trigger = (RefreshTrigger) mRefreshHeaderView;
                trigger.onStart(automatic, headerHeight, finalHeight);
            }
        }

        @Override
        public void onMove(boolean finished, boolean automatic, int moved) {
            if (mRefreshHeaderView != null && mRefreshHeaderView instanceof RefreshTrigger) {
                RefreshTrigger trigger = (RefreshTrigger) mRefreshHeaderView;
                trigger.onMove(finished, automatic, moved);
            }
        }

        @Override
        public void onRefresh() {
            if (mRefreshHeaderView != null && mRefreshHeaderView instanceof RefreshTrigger) {
                RefreshTrigger trigger = (RefreshTrigger) mRefreshHeaderView;
                trigger.onRefresh();
            }
        }

        @Override
        public void onRelease() {
            if (mRefreshHeaderView != null && mRefreshHeaderView instanceof RefreshTrigger) {
                RefreshTrigger trigger = (RefreshTrigger) mRefreshHeaderView;
                trigger.onRelease();
            }
        }

        @Override
        public void onComplete() {
            if (mRefreshHeaderView != null && mRefreshHeaderView instanceof RefreshTrigger) {
                RefreshTrigger trigger = (RefreshTrigger) mRefreshHeaderView;
                trigger.onComplete();
            }
        }

        @Override
        public void onReset() {
            if (mRefreshHeaderView != null && mRefreshHeaderView instanceof RefreshTrigger) {
                RefreshTrigger trigger = (RefreshTrigger) mRefreshHeaderView;
                trigger.onReset();
            }
        }
    };

    private OnLoadMoreScrollListener mOnLoadMoreScrollListener = new OnLoadMoreScrollListener() {
        @Override
        public void onLoadMore(RecyclerView recyclerView) {
            if (mOnLoadMoreListener != null && mStatus == STATUS_DEFAULT) {
                mOnLoadMoreListener.onLoadMore();
            }
        }
    };

    private void setStatus(int status) {
        this.mStatus = status;
        if (DEBUG) {
            printStatusLog();
        }
    }

    private void printStatusLog() {
        Log.i(TAG, getStatusLog(mStatus));
    }

    private String getStatusLog(int status) {
        final String statusLog;
        switch (status) {
            case STATUS_DEFAULT:
                statusLog = "status_default";
                break;

            case STATUS_SWIPING_TO_REFRESH:
                statusLog = "status_swiping_to_refresh";
                break;

            case STATUS_RELEASE_TO_REFRESH:
                statusLog = "status_release_to_refresh";
                break;

            case STATUS_REFRESHING:
                statusLog = "status_refreshing";
                break;
            default:
                statusLog = "status_illegal!";
                break;
        }
        return statusLog;
    }
} public interface OnLoadMoreListener {

    void onLoadMore();

} public class MyApplication extends Application {
    private static int mainThreadId;
    private static Handler handler;
    private static Context mContext;
    private static ThreadManager.ThreadPool mThreadPool;

//    private static MyApplication sMyApplication;


    public void setThreadPool(ThreadManager.ThreadPool threadPool) {
        mThreadPool = threadPool;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mContext = getApplicationContext();
        handler = new Handler();
        mainThreadId = android.os.Process.myTid();
        mThreadPool = ThreadManager.getThreadPool();

        initBugly();


    }

    /**
     * 初始化bugly
     */
    private void initBugly() {
    // 获取当前包名
        String packageName = mContext.getPackageName();
    // 获取当前进程名
        String processName = getProcessName(android.os.Process.myPid());
    // 设置是否为上报进程
        CrashReport.UserStrategy strategy = new CrashReport.UserStrategy(mContext);
        strategy.setUploadProcess(processName == null || processName.equals(packageName));
        CrashReport.initCrashReport(getApplicationContext(), "7a544c9222", false);
    }

    /**
     * 获取进程号对应的进程名
     *
     * @param pid 进程号
     * @return 进程名
     */
    private static String getProcessName(int pid) {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader("/proc/" + pid + "/cmdline"));
            String processName = reader.readLine();
            if (!TextUtils.isEmpty(processName)) {
                processName = processName.trim();
            }
            return processName;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException exception) {
                exception.printStackTrace();
            }
        }
        return null;
    }


//    public static MyApplication getInstance() {
//        // if语句下是不会走的，Application本身已单例
//        if (sMyApplication == null) {
//            synchronized (MyApplication.class) {
//                if (sMyApplication == null) {
//                    sMyApplication = new MyApplication();
//                }
//            }
//        }
//        return sMyApplication;
//    }


    public static Context getContext() {
        return mContext;
    }

    public static Handler getHandler() {
        return handler;
    }


    public static int getMainThreadId() {
        return mainThreadId;
    }

    public static ThreadManager.ThreadPool getThreadPool() {
        return mThreadPool;
    }
} public class DensityUtils {

    public static int getScreenWidth(Context context) {
        DisplayMetrics dm = new DisplayMetrics();
        ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm);
        return dm.widthPixels;
    }

    public static int getScreenHeight(Context context) {
        DisplayMetrics dm = new DisplayMetrics();
        ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm);
        return dm.heightPixels;
    }

    public static int getScreenHeightWithDecorations(Context context) {
        int heightPixels;
        WindowManager w = ((Activity) context).getWindowManager();
        Display d = w.getDefaultDisplay();
        android.graphics.Point realSize = new android.graphics.Point();
        try {
            Display.class.getMethod("getRealSize", android.graphics.Point.class).invoke(d, realSize);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        heightPixels = realSize.y;
        return heightPixels;
    }

    /**
     * 获得状态栏的高度
     * 注意：该方法只能在Activity类中使用，在测试模式下失败
     * @param context
     * @return
     */
    public static int getStatusBarHeight(Context context) {
        int statusBarHeight = -1;
        try {
            Class<?> clazz = Class.forName("com.android.internal.R$dimen");
            Object object = clazz.newInstance();
            int height = Integer.parseInt(clazz.getField("status_bar_height")
                    .get(object).toString());
            statusBarHeight = context.getResources().getDimensionPixelSize(height);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return statusBarHeight;
    }


    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    public static int px2dip(Context context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }
} public class LocalCacheUtils {
    private static final String TAG = LocalCacheUtils.class.getSimpleName();

    /**
     * @param url     传入获取信息的网址，作为保存缓存的文件名
     * @param content 传入要缓存的信息
     */
    public static void setDiskLruCache(String url, String content) {
        Context context = UIUtils.getContext();
        DiskLruCache mDiskLruCache = null;
        try {
            File cacheDir = getDiskCacheDir(context, "news");
            if (!cacheDir.exists()) {
                cacheDir.mkdirs();
            }
            mDiskLruCache = DiskLruCache.open(cacheDir, getAppVersion(context), 1, 10 * 1024 * 1024);

            String key = hashKeyForDisk(url);
            DiskLruCache.Editor editor = mDiskLruCache.edit(key);
            if (editor != null) {
                OutputStream outputStream = editor.newOutputStream(0);
                if (setLocalCache(content, outputStream)) {
                    editor.commit();
                } else {
                    editor.abort();
                }
            }
            mDiskLruCache.flush();

            Log.d(TAG, "setDiskLruCache: 写入缓存成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 获取新闻缓存目录地址
     *
     * @param context
     * @param uniqueName
     * @return
     */
    public static File getDiskCacheDir(Context context, String uniqueName) {
        return new File(getCachePath(context) + File.separator + uniqueName);
    }

    /**
     * 获取缓存目录
     * @param context
     * @return
     */
    public static String getCachePath(Context context){
        String cachePath;
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
                || !Environment.isExternalStorageRemovable()) {
            // 当SD卡存在或者SD卡不可被移除的时候，就调用getExternalCacheDir()方法来获取缓存路径，否则就调用getCacheDir()方法来获取缓存路径
            // 路径为/sdcard/Android/data/<application package>/cache
            cachePath = context.getExternalCacheDir().getPath();
        } else {
            //  路径为/data/data/<application package>/cache
            cachePath = context.getCacheDir().getPath();
        }
        return cachePath;
    }

    /**
     * 获取当前版本号
     *
     * @param context
     * @return 返回当前应用的版本号
     */
    private static int getAppVersion(Context context) {
        try {
            PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            return info.versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return 1;
    }


    private static final String LOCAL_CACHE_PATH = Environment
            .getExternalStorageDirectory().getAbsolutePath() + "/NetEasyNews_Cache";

    // 写本地缓存
    public static boolean setLocalCache(String content, OutputStream outputStream) {

        BufferedOutputStream out = null;
        try {
            out = new BufferedOutputStream(outputStream, 8 * 1024);
            out.write(content.getBytes());
            return true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            Log.d(TAG, "setLocalCache: 没有找到可写入的文件");
        } catch (IOException e) {
            e.printStackTrace();
            Log.d(TAG, "setLocalCache: 写入文件失败，写入流被关闭或者其他I/O原因");
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
                Log.d(TAG, "setLocalCache: I/O流关闭错误");
            }
        }
        return false;
    }

    /**
     * 读取磁盘缓存
     * @param url
     * @return
     */
    public static String getLocalCache( String url) {
        Context context = UIUtils.getContext();
        DiskLruCache mDiskLruCache = null;
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader br = null;
        InputStream is = null;
        // 获取缓存文件夹
        File cacheDir = getDiskCacheDir(context, "news");
        if (!cacheDir.exists()) {
            cacheDir.mkdirs();
        }
        try {
            mDiskLruCache = DiskLruCache.open(cacheDir, getAppVersion(context), 1, 10 * 1024 * 1024);
            String key = hashKeyForDisk(url);
            DiskLruCache.Snapshot snapShot = mDiskLruCache.get(key);
            if (snapShot != null) {
                is = snapShot.getInputStream(0);
                br = new BufferedReader(new InputStreamReader(is, "utf-8"));
                String str;
                while ((str = br.readLine()) != null) {
                    stringBuilder.append(str);
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭流
            IOUtils.close(br);
            IOUtils.close(is);
        }
//        Log.d(TAG, "getLocalCache: " + stringBuilder.toString());
        return stringBuilder.toString();
    }

    /**
     * 清除缓存
     * @param url     根据url清除缓存
     * @return
     */
    public static boolean removeCache(String url) {
        Context context = UIUtils.getContext();
        DiskLruCache mDiskLruCache = null;
        File cacheDir = getDiskCacheDir(context, "news");
        if (!cacheDir.exists()) {
            cacheDir.mkdirs();
        }
        try {
            mDiskLruCache = DiskLruCache.open(cacheDir, getAppVersion(context), 1, 10 * 1024 * 1024);
            String key = hashKeyForDisk(url);
            mDiskLruCache.remove(key);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 判断缓存文件是否存在
     * @param url   传入url地址作为缓存文件的文件名（经过MD5加密）
     * @return
     */
    public static boolean hasCacheFile(String url) {
        Context context = UIUtils.getContext();
        File cacheDir = getDiskCacheDir(context, "news");
        // 判断缓存目录是否存在，不存在返回false
        if (!cacheDir.exists()) {
            return false;
        }
        // 存在的时候继续判断
        String key = hashKeyForDisk(url);
        File cacheFile = new File(cacheDir.getAbsolutePath() + File.separator +key);
        Log.d(TAG, "hasCacheFile: 缓存文件名为" + cacheFile.getAbsolutePath());
        // 判断缓存文件是否存在，不存在返回false
        if (!cacheDir.exists()) {
            Log.d(TAG, "hasCacheFile: 不存在缓存文件");
            return false;
        }
        return true;
    }

} public class LogUtils {
    /**
     * 日志输出级别NONE
     */
    public static final int LEVEL_NONE = 0;
    /**
     * 日志输出级别E
     */
    public static final int LEVEL_ERROR = 1;
    /**
     * 日志输出级别W
     */
    public static final int LEVEL_WARN = 2;
    /**
     * 日志输出级别I
     */
    public static final int LEVEL_INFO = 3;
    /**
     * 日志输出级别D
     */
    public static final int LEVEL_DEBUG = 4;
    /**
     * 日志输出级别V
     */
    public static final int LEVEL_VERBOSE = 5;

    /** 日志输出时的TAG */
//	private static String mTag = "LogUtils";
    /**
     * 是否允许输出log
     */
    private static int mDebuggable = LEVEL_DEBUG;

    /**
     * 以级别为 d 的形式输出LOG
     */
    public static void v(String tag, String msg) {
        if (mDebuggable >= LEVEL_VERBOSE) {
            Log.v(tag, msg);
        }
    }

    /**
     * 以级别为 d 的形式输出LOG
     */
    public static void d(String tag, String msg) {
        if (mDebuggable >= LEVEL_DEBUG) {
            Log.d(tag, msg);
        }
    }

    /**
     * 以级别为 i 的形式输出LOG
     */
    public static void i(String tag, String msg) {
        if (mDebuggable >= LEVEL_INFO) {
            Log.i(tag, msg);
        }
    }

    /**
     * 以级别为 w 的形式输出LOG
     */
    public static void w(String tag, String msg) {
        if (mDebuggable >= LEVEL_WARN) {
            Log.w(tag, msg);
        }
    }

    /**
     * 以级别为 w 的形式输出Throwable
     */
    public static void w(String tag, Throwable tr) {
        if (mDebuggable >= LEVEL_WARN) {
            Log.w(tag, "", tr);
        }
    }

    /**
     * 以级别为 w 的形式输出LOG信息和Throwable
     */
    public static void w(String tag, String msg, Throwable tr) {
        if (mDebuggable >= LEVEL_WARN && null != msg) {
            Log.w(tag, msg, tr);
        }
    }

    /**
     * 以级别为 e 的形式输出LOG
     */
    public static void e(String tag, String msg) {
        if (mDebuggable >= LEVEL_ERROR) {
            Log.e(tag, msg);
        }
    }

    /**
     * 以级别为 e 的形式输出Throwable
     */
    public static void e(String tag, Throwable tr) {
        if (mDebuggable >= LEVEL_ERROR) {
            Log.e(tag, "", tr);
        }
    }

    /**
     * 以级别为 e 的形式输出LOG信息和Throwable
     */
    public static void e(String tag, String msg, Throwable tr) {
        if (mDebuggable >= LEVEL_ERROR && null != msg) {
            Log.e(tag, msg, tr);
        }
    }
} public class NetWorkUtil {
    /**
     * 判断是否有网络连接
     *
     * @param context
     * @return
     */
    public static boolean isNetworkConnected(Context context) {
        if (context != null) {
            // 获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)
            ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            // 获取NetworkInfo对象
            NetworkInfo networkInfo = manager.getActiveNetworkInfo();
            //判断NetworkInfo对象是否为空
            if (networkInfo != null)
                return networkInfo.isAvailable();
        }
        return false;
    }


    /**
     * 判断WIFI网络是否可用
     *
     * @param context
     * @return
     */
    public static boolean isWifiConnected(Context context) {
        if (context != null) {
            // 获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)
            ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            // 获取NetworkInfo对象
            NetworkInfo networkInfo = manager.getActiveNetworkInfo();
            //判断NetworkInfo对象是否为空 并且类型是否为WIFI
            if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI)
                return networkInfo.isAvailable();
        }        return false;
    }

    /**
     * 判断MOBILE网络是否可用
     *
     * @param context
     * @return
     */
    public static boolean isMobileConnected(Context context) {
        if (context != null) {
            //获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)
            ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            //获取NetworkInfo对象
            NetworkInfo networkInfo = manager.getActiveNetworkInfo();
            //判断NetworkInfo对象是否为空 并且类型是否为MOBILE
            if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE)
                return networkInfo.isAvailable();
        }
        return false;
    }
    /**
     * 获取当前网络连接的类型信息
     * 原生
     *
     * @param context
     * @return
     */    public static int getConnectedType(Context context) {
        if (context != null) {
            //获取手机所有连接管理对象
            ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            //获取NetworkInfo对象
            NetworkInfo networkInfo = manager.getActiveNetworkInfo();
            if (networkInfo != null && networkInfo.isAvailable()) {
                //返回NetworkInfo的类型
                return networkInfo.getType();
            }
        }
        return -1;
    }
    /**
     * 获取当前的网络状态 ：没有网络-0：WIFI网络1：4G网络-4：3G网络-3：2G网络-2
     * 自定义
     *
     * @param context
     * @return
     */
    public static int getAPNType(Context context) {
        //结果返回值
        int netType = 0;
        //获取手机所有连接管理对象
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        //获取NetworkInfo对象
        NetworkInfo networkInfo = manager.getActiveNetworkInfo();
        //NetworkInfo对象为空 则代表没有网络
        if (networkInfo == null) {
            return netType;
        }
        //否则 NetworkInfo对象不为空 则获取该networkInfo的类型
        int nType = networkInfo.getType();
        if (nType == ConnectivityManager.TYPE_WIFI) {
            //WIFI
            netType = 1;
        } else if (nType == ConnectivityManager.TYPE_MOBILE) {
            int nSubType = networkInfo.getSubtype();
            TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            //3G   联通的3G为UMTS或HSDPA 电信的3G为EVDO
            if (nSubType == TelephonyManager.NETWORK_TYPE_LTE
                    && !telephonyManager.isNetworkRoaming()) {
                netType = 4;
            } else if (nSubType == TelephonyManager.NETWORK_TYPE_UMTS
                    || nSubType == TelephonyManager.NETWORK_TYPE_HSDPA
                    || nSubType == TelephonyManager.NETWORK_TYPE_EVDO_0
                    && !telephonyManager.isNetworkRoaming()) {
                netType = 3;
                //2G 移动和联通的2G为GPRS或EGDE，电信的2G为CDMA
            } else if (nSubType == TelephonyManager.NETWORK_TYPE_GPRS
                    || nSubType == TelephonyManager.NETWORK_TYPE_EDGE
                    || nSubType == TelephonyManager.NETWORK_TYPE_CDMA
                    && !telephonyManager.isNetworkRoaming()) {
                netType = 2;
            } else {
                netType = 2;
            }
        }
        return netType;
    }
    /**
     * 判断GPS是否打开
     *ACCESS_FINE_LOCATION权限
     * @param context
     * @return
     */
    public static boolean isGPSEnabled(Context context) {
        //获取手机所有连接LOCATION_SERVICE对象
        LocationManager locationManager = ((LocationManager) context.getSystemService(Context.LOCATION_SERVICE));
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    }
} public class ThreadManager {

	private static ThreadPool mThreadPool;

	/**
	 *  创建线程池，使用单例模式，在Applicaiton中初始化
	 * @return	返回线程池
     */
	public static ThreadPool getThreadPool() {
		if (mThreadPool == null) {
			synchronized (ThreadManager.class) {
				if (mThreadPool == null) {
					int cpuCount = Runtime.getRuntime().availableProcessors();// 获取cpu数量
					System.out.println("cup个数:" + cpuCount);

					// int threadCount = cpuCount * 2 + 1;//线程个数
					int threadCount = 10;
					mThreadPool = new ThreadPool(threadCount, threadCount, 1L);
				}
			}
		}

		return mThreadPool;
	}

	// 线程池
	public static class ThreadPool {

		private int corePoolSize;// 核心线程数
		private int maximumPoolSize;// 最大线程数
		private long keepAliveTime;// 休息时间

		private ThreadPoolExecutor executor;

		private ThreadPool(int corePoolSize, int maximumPoolSize,
				long keepAliveTime) {
			this.corePoolSize = corePoolSize;
			this.maximumPoolSize = maximumPoolSize;
			this.keepAliveTime = keepAliveTime;
		}


		public void execute(Runnable r) {
			if (executor == null) {
				executor = new ThreadPoolExecutor(corePoolSize,
						maximumPoolSize, keepAliveTime, TimeUnit.SECONDS,
						new LinkedBlockingQueue<Runnable>(),
						Executors.defaultThreadFactory(), new AbortPolicy());
				// 参1:核心线程数;参2:最大线程数;参3:线程休眠时间;参4:时间单位;参5:线程队列;参6:生产线程的工厂;参7:线程异常处理策略
			}

			// 线程池执行一个Runnable对象, 具体运行时机线程池说了算
			executor.execute(r);
		}

		// 取消任务
		public void cancel(Runnable r) {
			if (executor != null) {
				// 从线程队列中移除对象
				executor.getQueue().remove(r);
			}
		}

	}
} public class ToastUtils {
    public static void showLong(String value){
        if (!TextUtils.isEmpty(value)){
            Toast.makeText(MyApplication.getContext(), value, Toast.LENGTH_LONG).show();
        }
    }

    public static void showShort(String value){
        if (!TextUtils.isEmpty(value)){
            Toast.makeText(MyApplication.getContext(), value, Toast.LENGTH_SHORT).show();
        }
    }
} public class PicDetailActivity extends BaseActivity implements DefineView {
    private final String TAG = PicDetailActivity.class.getSimpleName();

    private String tid; // 图片频道id，用于打开新闻详情页
    private String setid;  //   图片的分类

    private ViewPager mViewPager;
    private ArrayList<BaseFragment> mBaseFragmentArrayList;
    private static final String KEY_TID = "TID";  //频道id
    private static final String SETID = "SETID";
    private ThreadManager.ThreadPool mThreadPool;   // 线程池
    private ImageDetailBean mImageDetailBean;
    private Context mContext;
    private boolean isGone;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pic_detail);
        mContext = this;
        initView();
        initValidata();
        initListener();
    }

    @Override
    public void initView() {
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setDisplayShowTitleEnabled(false);
            actionBar.setHomeAsUpIndicator(R.drawable.icon_back);
        }


        mViewPager = (ViewPager) findViewById(R.id.vp_pic);

    }

    @Override
    public void initValidata() {
        mThreadPool = ThreadManager.getThreadPool();
        Intent intent = getIntent();
        tid = intent.getStringExtra(KEY_TID);
        setid = intent.getStringExtra(SETID);
        requestData();
    }

    @Override
    public void initListener() {

    }

    @Override
    public void bindData() {
        PicDetailAdapter picDetailAdapter = new PicDetailAdapter(mImageDetailBean);
        mViewPager.setAdapter(picDetailAdapter);
        mViewPager.setCurrentItem(0);
    }


    public void requestData() {
//        mUrl = Api.CommonUrl + Api.toutiaoId + "/" + mStartIndex + Api.endUrl;
//        Log.d(TAG, "mUrl地址为: " + mUrl);
//        http://c.m.163.com/nc/article/list/T1467284926140/0-20.html
//        http://c.m.163.com/nc/article/list/T1348647909107/0-20.html

        mThreadPool.execute(new Runnable() {
            @Override
            public void run() {
////                String url = Api.PictureDetailUrl + getTid() + "/"+getAllParams(params) + ".json";

                String url = Api.PictureDetailUrl + tid + "/" + setid + ".json";
                HttpHelper.get(url, new HttpCallbackListener() {
                    @Override
                    public void onSuccess(String result) {
                        mImageDetailBean = DataParse.ImageDetail(result);
                        UIUtils.runOnUIThread(new Runnable() {
                            @Override
                            public void run() {
                                LogUtils.d(TAG, ": 解析id" + mImageDetailBean);
                                if (mImageDetailBean != null) {
//                                    mPhotosBeens = mImageDetailBean.getPhotos();
                                    bindData();
                                }
                            }
                        });
                    }

                    @Override
                    public void onError(Exception e) {

                    }
                });
            }
        });

    }

    public class PicDetailAdapter extends PagerAdapter {

        private ImageDetailBean mImageDetailBean;

        public PicDetailAdapter(ImageDetailBean imageDetailBean) {
            mImageDetailBean = imageDetailBean;
        }

        @Override
        public int getCount() {
            return mImageDetailBean.getPhotos().size();
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            View view = View.inflate(mContext, R.layout.fragment_pic_detail, null);
            ImageView iv_pic = (ImageView) view.findViewById(R.id.iv_pic);
            TextView tv_title = (TextView) view.findViewById(R.id.tv_title);
            TextView tv_pic_sum = (TextView) view.findViewById(R.id.tv_pic_sum);
            final ScrollView sv_content = (ScrollView) view.findViewById(R.id.sv_content);
            TextView tv_pic_content = (TextView) view.findViewById(R.id.tv_pic_content);
            String setName = mImageDetailBean.getSetname();
            String postid = mImageDetailBean.getPostid();
            ImageDetailBean.PhotosBean photosBean = mImageDetailBean.getPhotos().get(position);
            LogUtils.d(TAG, setName);
            String title = photosBean.getImgtitle();
            String note = photosBean.getNote();
            isGone = false;
            if (title != null && !title.equals("")) {
                tv_title.setText(title);
            } else if (setName != null && !setName.equals("")){
                tv_title.setText(setName);
            } else {
                tv_title.setText(postid);
            }

            if (note != null) {
                tv_pic_content.setText(note);
                isGone = false;
            } else {
                sv_content.setVisibility(View.GONE);
                isGone = true;
            }

            tv_pic_sum.setText((position + 1) + "/" + mImageDetailBean.getPhotos().size());

            Glide.with(mContext)
                    .load(photosBean.getImgurl())
                    .placeholder(R.drawable.defaultbg)
                    .centerCrop()
                    .crossFade()
                    .into(iv_pic);

            iv_pic.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (isGone) {
                        sv_content.setVisibility(View.VISIBLE);
                        isGone = false;
                    } else {
                        sv_content.setVisibility(View.GONE);
                        isGone = true;
                    }
                }
            });

            container.addView(view);

            return view;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }
    }


} public class PicListAdapter extends RecyclerView.Adapter<PicListAdapter.ViewHolder> {

    private Context mContext;
    private ArrayList<PicListBean> mPicListBeens;
    private OnItemClickListener mOnItemClickListener;

    public PicListAdapter(Context context, ArrayList<PicListBean> picListBeens) {
        mContext = context;
        mPicListBeens = picListBeens;

    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = View.inflate(mContext, R.layout.item_pic_layout, null);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        PicListBean picListBean = mPicListBeens.get(position);

        String imageSrc = picListBean.getCover();
        String title = picListBean.getSetname();

        holder.tv_title.setText(title);

        Glide.with(mContext)
                .load(imageSrc)
                .placeholder(R.drawable.defaultbg)
                .crossFade()
                .into(holder.iv_pic);

        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getIAdapterPosition();
                final PicListBean picListBean = mPicListBeens.get(position);
                if (mOnItemClickListener != null) {
                    mOnItemClickListener.onItemClick(position, picListBean, v);
                }
            }
        });

    }

    @Override
    public int getItemCount() {
        return mPicListBeens.size();
    }

    /**
     * 设置Item点击监听
     *
     * @param listener
     */
    public void setOnItemClickListener(OnItemClickListener listener) {
        this.mOnItemClickListener = listener;
    }


    public interface OnItemClickListener<T> {
        void onItemClick(int position, T t, View v);
    }

    public class ViewHolder extends IViewHolder {

        public LinearLayout rl_root;
        public ImageView iv_pic;
        public TextView tv_title;


        public ViewHolder(View itemView) {
            super(itemView);
            rl_root = (LinearLayout) itemView.findViewById(R.id.rl_root);
            iv_pic = (ImageView) itemView.findViewById(R.id.iv_pic);
            tv_title = (TextView) itemView.findViewById(R.id.tv_title);
        }
    }


} public class PicListBean {

    /**
     * desc : Hendo除了COS男版蜘蛛侠外更是挑战了一下原作中由蜘蛛侠女友温格所变身的女版蜘蛛，效果更是到位。女版蜘蛛侠会不会更厉害，更值得期待？
     * pvnum :
     * createdate : 2016-12-27 01:49:02
     * scover : http://img3.cache.netease.com/photo/0031/2016-12-27/s_C98O8VGL6LRK0031.jpg
     * setname : 女版蜘蛛侠会不会更厉害？值得期待！
     * cover : http://img4.cache.netease.com/photo/0031/2016-12-27/C98O8VGL6LRK0031.jpg
     * pics : ["http://img3.cache.netease.com/photo/0031/2016-12-27/C98O8UBL6LRK0031.jpg","http://img3.cache.netease.com/photo/0031/2016-12-27/C98O8UPE6LRK0031.jpg","http://img4.cache.netease.com/photo/0031/2016-12-27/C98O8UVI6LRK0031.jpg"]
     * clientcover1 :
     * replynum : 217
     * topicname :
     * setid : 91416
     * seturl : http://play.163.com/photoview/6LRK0031/91416.html
     * datetime : 2016-12-27 01:57:49
     * clientcover :
     * imgsum : 16
     * tcover : http://img4.cache.netease.com/photo/0031/2016-12-27/t_C98O8VGL6LRK0031.jpg
     */

//    private List<PicList> mPicLists;
//
//    public List<PicList> getPicLists() {
//        return mPicLists;
//    }
//
//    public void setPicLists(List<PicList> picLists) {
//        mPicLists = picLists;
//    }
//
//    public class PicList{
        private String desc;
        // 创建时间
        private String createdate;
        private String setname;
        private String cover;
        private String setid;
        private String seturl;
        // 发布时间
        private String datetime;
        // 图片总数
        private String imgsum;
        private List<String> pics;

        public String getDesc() {
            return desc;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }

        public String getCreatedate() {
            return createdate;
        }

        public void setCreatedate(String createdate) {
            this.createdate = createdate;
        }

        public String getSetname() {
            return setname;
        }

        public void setSetname(String setname) {
            this.setname = setname;
        }

        public String getCover() {
            return cover;
        }

        public void setCover(String cover) {
            this.cover = cover;
        }

        public String getSetid() {
            return setid;
        }

        public void setSetid(String setid) {
            this.setid = setid;
        }

        public String getSeturl() {
            return seturl;
        }

        public void setSeturl(String seturl) {
            this.seturl = seturl;
        }

        public String getDatetime() {
            return datetime;
        }

        public void setDatetime(String datetime) {
            this.datetime = datetime;
        }

        public String getImgsum() {
            return imgsum;
        }

        public void setImgsum(String imgsum) {
            this.imgsum = imgsum;
        }

        public List<String> getPics() {
            return pics;
        }

        public void setPics(List<String> pics) {
            this.pics = pics;
        }

    @Override
    public String toString() {
        return "PicListBean{" +
                "setname='" + setname + '\'' +
                ", cover='" + cover + '\'' +
                ", createdate='" + createdate + '\'' +
                '}';
    }


    //    }




} public class Api {



    public static final String host = "http://c.m.163.com/";

    // 普通栏目前缀, 示例： http://c.m.163.com/nc/article/list/T1467284926140/0-20.html
    public static final String CommonUrl = host + "nc/article/list/";

    // 图片栏目的前缀， 示例： http://pic.news.163.com/photocenter/api/list/0031/6LRK0031,6LRI0031/0/20.json
    // 推荐图片：0031， 新闻图片： 0001 ， 明星图片：0003
    public static final String PictureUrl = "http://pic.news.163.com/photocenter/api/list/";

    // 特殊频道前缀：热点、网易号适用
    public static final String SpecialColumn1 = "recommend/getSubDocPic?";

    // 特殊频道前缀:	视频/段子、美女、萌宠适用
    public static final String SpecialColumn2 = "recommend/getChanListNews?channel=";
    // 文章详情前缀
    public static final String DetailUrl = host + "nc/article/";

    // 普通新闻栏目的结尾，注意要在前面添加新闻从那一条开始获取
    // 如 ：http://c.m.163.com/nc/article/list/T1467284926140/0-20.html，获取最新的20条新闻
    // http://c.m.163.com/nc/article/list/T1467284926140/20-20.html，获取从第20条开始的后面20条新闻
    public static final String endUrl = "-20.html";

    // 所有特殊频道的结尾，如：热点、网易号、段子、美女、萌宠
    public static final String SpecialendUrl = "&size=10&offset=";

    /**
     * 新闻文章详情页链接尾部
     * 示例：http://c.m.163.com/nc/article/C8T2G5QL0511A99L/full.html
     * 其中postId ：C8T2G5QL0511A99L
     */
    public static final String endDetailUrl = "/full.html";

    /**
     * 图片新闻详情页连接
     * 链接示例： http://c.m.163.com/photo/api/set/0031/13897.json
     * 图片详情页：0031为图片频道（列表连接后面的0031），13897为图片新闻setid
     */
    public static final String PictureDetailUrl = host + "photo/api/set/";
    // 图片新闻详情页结尾
    public static final String endPictureDetailUrl = ".json";


    /**
     * 视频详情链接
     *  示例： http://c.m.163.com/nc/video/detail/VC5BA022H.html
     *  其中VC5BA022H是视频的vid
     */
    public static final String videoDetailUrl = host + "nc/video/detail/";
    // 视频详情链接尾部
    public static final String EndUrlVideoDetailUrl = ".html";


    // 独家
    public static final String zhenhuaId = "T1370583240249";

    // NBA
    public static final String NBAId = "T1348649145984";

    // 头条
    public static final String toutiaoId = "T1348647909107";

    // 社会
    public static final String shehuiId = "T1348648037603";

    // 历史
    public static final String lishiId = "T1368497029546";

    // 军事
    public static final String junshiId = "T1348648141035";

    // 哒哒趣闻
    public static final String dadaId = "T1444289532601";

    // 航空
    public static final String aviationId = "T1474271789612";

    // 要闻
    public static final String yaowenspecialId = "T1467284926140";

    // 娱乐
    public static final String yuleId = "T1348648517839";

    // 影视歌
    public static final String dianyingId = "T1348648650048";

    // 财经
    public static final String caijingId = "T1348648756099";

    // 股票
    public static final String stockId = "T1473054348939";

    // 彩票
    public static final String caipiaoId = "T1356600029035";

    // 体育
    public static final String tiyuId = "T1348649079062";

    // 中国足球
    public static final String zhongchaoId = "T1348649503389";

    // 国际足球
    public static final String zuqiuId = "T1348649176279";

    // CBA
    public static final String CBAId = "T1348649475931";

    // 跑步
    public static final String paobuId = "T1411113472760";

    // 科技
    public static final String kejiId = "T1348649580692";

    // 手机
    public static final String shoujiId = "T1348649654285";

    // 数码
    public static final String shumaId = "T1348649776727";

    // 智能
    public static final String zhinengId = "T1351233117091";

    // 轻松一刻
    public static final String qingsongyikeId = "T1350383429665";

    // 云课堂
    public static final String gongkaikeId = "T1421997195219";

    // 态度公开课
    public static final String attitudeopenId = "T1456394562871";

    // 汽车
    public static final String qicheId = "T1348654060988";

    // 房产
    public static final String fangchanId = "T1348654085632";

    // 家居
    public static final String jiajuId = "T1348654105308";

    // 游戏
    public static final String youxiId = "T1348654151579";

    // 旅游
    public static final String lvyouId = "T1348654204705";

    // 健康
    public static final String jiankangId = "T1414389941036";

    // 读书
    public static final String dushuId = "T1401272877187";

    // 酒香
    public static final String jiuxiangId = "T1385429690972";

    // 教育
    public static final String jiaoyuId = "T1348654225495";

    // 亲子
    public static final String qinziId = "T1397116135282";

    // 暴雪游戏
    public static final String baoxueId = "T1397016069906";

    // 漫画
    public static final String manhuaId = "T1444270454635";

    // 二次元
    public static final String erciyuanlanmuId = "T1481105123675";

    // 态度营销
    public static final String taiduyingxiaoId = "T1464592736048";

    // 时尚
    public static final String nvrenId = "T1348650593803";

    // 情感
    public static final String qingganId = "T1348650839000";

    // 政务
    public static final String zhengwuId = "T1414142214384";

    // 艺术
    public static final String ArtId = "T1441074311424";

    // 阳光法院
    public static final String yangguangfayuanId = "T1482470888760";

    // 跟贴
    public static final String specialCommentId = "T1419315959525";

    // 海外
    public static final String zongheId = "T1462426218632";


    // 本地   暂不使用
    public static final String specialLocalId = "T1419316531256";

    // 博客
    public static final String specialBlogId = "T1419386532423";

    // 论坛
    public static final String specialBBSId = "T1419386592923";


    // 直播
    public static final String specialLiveId = "T1433137697241";


    // 图片新闻尾部，需要在签名添加参数，可获得从某条新闻之后的20条新闻
    // 示例 ： http://pic.news.163.com/photocenter/api/list/0001/00AN0001,00AO0001/0/20.json
    public static final String endPicture = "/20.json";
    // 图片
    public static final String specialPictureId = "T1419316384474";

    // 推荐图片：0031/6LRK0031,6LRI0031/    应使用瀑布流
    public static final String RecommendPictureId = "0031";
    public static final String RecommendPicture = "/6LRK0031,6LRI0031/";

    // 新闻图片：0001/00AP0001,3R710001,4T8E0001/    横向排版
    public static final String NewsPictureId = "0001";
    public static final String NewsPicture = "/00AP0001,3R710001,4T8E0001/";
    // 热点图片：0001/00AN0001,00AO0001/     横向排版
    public static final String HotPicture = "/00AN0001,00AO0001/";

    // 明星图片：0003/00AJ0003,0AJQ0003,3LF60003,00B70003,00B50003/      瀑布流排版
    public static final String StarPictureId = "0003";
    public static final String StarPicture = "/00AJ0003,0AJQ0003,3LF60003,00B70003,00B50003/";



    /**
     *   特殊格式新闻：
     *   下面几类连接基本一致：
     *   热点、网易号类的新闻连接形式差不多，但是网易号多了from参数
     *   使用getSubDocPic
     *
     *   段子、美女、萌宠连接基本一致
     *   使用	getChanListNews
     **/
    // 热点
    public static final String specialRedianId = "T1427878984398";
    // 热点url
    public static final String RedianUrl = host + SpecialColumn1 + SpecialendUrl;

    // 网易号
    public static final String specialSubId = "T1449126525962";
    // 网易号url
    public static final String WangYiHaoUrl = host + SpecialColumn1 + "from=netease_h" +SpecialendUrl;

    // 下列为特殊频道URL， 统一连接形式为：
    // http://c.m.163.com/recommend/getChanListNews?channel=T1419316284722&size=10&offset=
    public static final String specialURL = host + SpecialColumn2;

    // 视频
    // http://c.m.163.com/recommend/getChanListNews?channel=T1457068979049&offset=0&size=20&devId=44t6%2B5mG3ACAOlQOCLuIHg%3D%3D
    public static final String specialVideoId = "T1457068979049";
    // 手机开发id号，任意手机的开发Id号都可以
    public static final String devId = "&devId=44t6%2B5mG3ACAOlQOCLuIHg%3D%3D";

    // 段子
    public static final String specialJokeId = "T1419316284722";

    // 美女
    public static final String specialGirlId = "T1456112189138";

    // 萌宠
    public static final String specialAnimalId = "T1456112438822";

    // 热点视频 http://c.m.163.com/nc/video/list/V9LG4B3A0/n/10-10.html
    public static final String Video = host + "nc/video/list/";
    public static final String VideoCenter = "/n/";
    public static final String videoEndUrl = "-20.html";
    // 热点视频
    public static final String VideoReDianId = "V9LG4B3A0";
    // 推荐视频
    // http://c.m.163.com/recommend/getChanListNews?channel=T1457068979049&offset=0&size=20&devId=44t6%2B5mG3ACAOlQOCLuIHg%3D%3D
    public static final String VideorecommendId = "T1457068979049";
    // 搞笑视屏 http://c.m.163.com/nc/video/list/VAP4BFE3U/y/10-10.html
    // 美女视频 http://c.m.163.com/nc/video/list/VAP4BG6DL/y/0-10.html
    // 新闻现场 http://c.m.163.com/nc/video/list/VAV3H6JSN/y/0-10.html
    // 萌物 http://c.m.163.com/nc/video/list/VAP4BFR16/y/0-10.html
    // 黑科技  http://c.m.163.com/nc/video/list/VBF8F2PKF/y/0-10.html
    // 二次元 http://c.m.163.com/nc/video/list/VBF8F1PSA/y/0-10.html
    // 涨姿势  http://c.m.163.com/nc/video/list/VBF8F3SGL/y/0-10.html
    //直播视
    public static final String VideoLive = "http://data.live.126.net/livechannel/previewlist.json";



} public interface DefineView {
	
   public void initView();  //初始化界面元素
   public void initValidata();  //初始化变量
   public void initListener();  //初始化监听器
   public void bindData();       //绑定数据
   
//   public void getPageData();// show page
//   public void getDataOk();  // data ok
//   public void getDataError();// data error
//   public void getDataRefresh();// data refresh
   
} public abstract class BaseFragment extends Fragment implements DefineView {
    public final int HANDLER_SHOW_NEWS = 11;
    public final int HANDLER_SHOW_ERROR = 12;
    public final int HANDLER_SHOW_REFRESH_LOADMORE = 13;
    public final int HANDLER_SHOW_REFRESH_LOADMORE_ERRO = 15;


    private final String TAG = BaseFragment.class.getSimpleName();

    /**
     * 设置toolbar标题居中，没有返回键
     * @param view
     * @param id    toolbar的id
     * @param titleId   textView的id
     * @param titleString   textView设置的文字
     * @return  返回toolbar
     */
    public Toolbar initToolbar(View view, int id, int titleId, int titleString) {
        Toolbar toolbar = (Toolbar) view.findViewById(id);
//        toolbar.setTitle("");
        TextView textView = (TextView) view.findViewById(titleId);
        textView.setText(titleString);
        AppCompatActivity activity = (AppCompatActivity) getActivity();
        activity.setSupportActionBar(toolbar);
        android.support.v7.app.ActionBar actionBar = activity.getSupportActionBar();
        if (actionBar != null){
            actionBar.setDisplayHomeAsUpEnabled(false);
            actionBar.setDisplayShowTitleEnabled(false);
        }
        return toolbar;
    }

    /**
     *
     * @param key
     * @return  返回true表示是最新的保存的，返回false表示保存已经超过3个小时
     */
    public boolean isLastNews(String key) {
        long threeHour = 3 * 60 * 60 * 1000;
        long currentTime = System.currentTimeMillis();
        long saveTime = getUpdateTime(key, currentTime);
        // 判断保存缓存的时间与现在的时间是否超过3小时，没有超过就读取缓存
        long ll = currentTime - saveTime;

        if (ll <= threeHour) {
            LogUtils.d(TAG, "saveTime  :  " + saveTime + "   ll:  " + ll + " ll < threeHour " + (ll < threeHour));
            return true;
        } else {
            LogUtils.d(TAG, "saveTime  :  " + saveTime + "   ll:  " + ll + " ll > threeHour " + (ll > threeHour));
            return false;
        }
    }

    // 保存缓存
    public void saveCache(String url, String content){
        if (LocalCacheUtils.hasCacheFile(url)) {
            // 清除之前的缓存
            LocalCacheUtils.removeCache(url);
        }
        // 保存缓存
        LocalCacheUtils.setDiskLruCache(url, content);
    }

    // 设置保存缓存的时间
    public static void saveUpdateTime(String key, long value) {
        PrefUtils.setLong(MyApplication.getContext(), "save_time", key, value);
    }

    // 获取保存缓存的时间
    public static long getUpdateTime(String key, long defValue) {
        long saveTime = PrefUtils.getLong(MyApplication.getContext(), "save_time", key, defValue);
        return saveTime;
    }
} public class DataParse {

    // 新闻列表解析
    public static ArrayList<NewsListNormalBean> NewsList(String json, String id) {
        // Gson, JsonObject
        // 使用JsonObject解析方式: 如果遇到{},就是JsonObject;如果遇到[], 就是JsonArray
        if (json != null) {
            JSONObject jsonObject = null;
            ArrayList<NewsListNormalBean> newsListNormalBeans = new ArrayList<>();
            try {
                jsonObject = new JSONObject(json);
                JSONArray array = jsonObject.getJSONArray(id);
                Gson gson = new Gson();
                for (int i = 0; i < array.length(); i++) {
                    String js = array.get(i).toString();
                    NewsListNormalBean newsListNormalBean = gson.fromJson(js, NewsListNormalBean.class);
                    newsListNormalBeans.add(newsListNormalBean);
                }
                return newsListNormalBeans;
            } catch (JSONException e) {
                e.printStackTrace();
                LogUtils.d(TAG, "parseJson: 数据解析错误");
            }
        } else {
            LogUtils.d(TAG, "parseData: 没有数据");
        }
        return null;
    }


    /**
     *  新闻详情页解析
     * @param result
     * @param tid
     * @return
     */
    public static NewsDetailBean NewsDetail(String result, String tid) {
        if (result != null) {
            JSONObject jsonObject = null;
            NewsDetailBean newsDetailBean;
            try {
                jsonObject = new JSONObject(result);
                String detail = jsonObject.getJSONObject(tid).toString();
                Gson gson = new Gson();
                newsDetailBean = gson.fromJson(detail, NewsDetailBean.class);
                return newsDetailBean;
            } catch (JSONException e) {
                e.printStackTrace();
                LogUtils.d(TAG, "parseJson: 数据解析错误");
            }
        } else {
            LogUtils.d(TAG, "parseData: 没有数据");
        }
        return null;
    }

    /**
     * 图片列表解析
     * @param result
     * @return
     */
    public static ArrayList<PicListBean> PicList(String result) {
        LogUtils.d("图片返回的数据", "parseData: " + result);
        ArrayList<PicListBean> PicListBeans = new ArrayList<>();
        Gson gson = new Gson();
        try {
            JSONArray jsonArray = new JSONArray(result);
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                PicListBean picListbean = gson.fromJson(jsonObject.toString(), PicListBean.class);
                PicListBeans.add(picListbean);
            }
            return PicListBeans;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 图片新闻详情页解析
     * @param result
     * @return
     */
    public static ImageDetailBean ImageDetail(String result) {
        ImageDetailBean imageDetailBean = null;
        if (result != null) {
            Gson gson = new Gson();
            imageDetailBean = gson.fromJson(result, ImageDetailBean.class);
            LogUtils.d(TAG, "parseJson: 数据解析成功");
        } else {
            LogUtils.d(TAG, "parseData: 没有数据");
        }
        return imageDetailBean;
    }

    /**
     * 视频列表解析
     * @param result
     * @return
     */
    public static ArrayList<VideoBean> VideoList(String result) {
        if (result != null) {
            JSONObject jsonObject = null;
            ArrayList<VideoBean> videoBeen = new ArrayList<>();
            try {
                jsonObject = new JSONObject(result);
                JSONArray array = jsonObject.getJSONArray("视频");
                Gson gson = new Gson();
                for (int i = 0; i < array.length(); i++) {
                    String js = array.get(i).toString();
                    VideoBean vieoBean = gson.fromJson(js, VideoBean.class);
                    videoBeen.add(vieoBean);
                }
                return videoBeen;
            } catch (JSONException e) {
                e.printStackTrace();
                LogUtils.d(TAG, "parseJson: 数据解析错误");
            }
        } else {
            LogUtils.d(TAG, "parseData: 没有数据");
        }
        return null;
    }

    /**
     * 视频详情页解析
     * @param result
     * @return
     */
    public static VideoBean VideoDetail(String result) {
        VideoBean bean = null;
        if (result != null) {
            Gson gson = new Gson();
            bean = gson.fromJson(result, VideoBean.class);
            LogUtils.d(TAG, "parseData: " + bean);
        }
        return bean;
    }
} public interface HttpCallbackListener {
    void onSuccess(String result);
    void onError(Exception e);
} @SuppressWarnings("deprecated")
public class HttpHelper {

    private static final String TAG = HttpHelper.class.getSimpleName();

    /**
     * get请求，获取返回字符串内容
     */
    public static void get(String url, HttpCallbackListener httpCallbackListener) {
        HttpGet httpGet = new HttpGet(url);
        execute(url, httpGet, httpCallbackListener);
    }

    /**
     * post请求，获取返回字符串内容
     */
    public static void post(String url, byte[] bytes, HttpCallbackListener httpCallbackListener) {
        HttpPost httpPost = new HttpPost(url);
        ByteArrayEntity byteArrayEntity = new ByteArrayEntity(bytes);
        httpPost.setEntity(byteArrayEntity);
        execute(url, httpPost, httpCallbackListener);
    }

    /**
     * 下载
     */
    public static void download(String url, HttpCallbackListener httpCallbackListener) {
        HttpGet httpGet = new HttpGet(url);
        execute(url, httpGet, httpCallbackListener);
    }

    /**
     * 执行网络访问
     */
    private static void execute(String url, HttpRequestBase requestBase, HttpCallbackListener httpCallbackListener) {
        boolean isHttps = url.startsWith("https://");//判断是否需要采用https
        AbstractHttpClient httpClient = HttpClientFactory.create(isHttps);
        HttpContext httpContext = new SyncBasicHttpContext(new BasicHttpContext());
        HttpRequestRetryHandler retryHandler = httpClient.getHttpRequestRetryHandler();//获取重试机制
        int retryCount = 0;
        boolean retry = true;
        while (retry) {
            try {
                HttpResponse response = httpClient.execute(requestBase, httpContext);//访问网络
                int stateCode  = response.getStatusLine().getStatusCode();
//                LogUtils.e(TAG, "http状态码：" + stateCode);
                if (response != null) {
                    if (stateCode == HttpURLConnection.HTTP_OK){
                        HttpResult httpResult = new HttpResult(response, httpClient, requestBase);
                        String result = httpResult.getString();
                        if (!TextUtils.isEmpty(result)){
                            httpCallbackListener.onSuccess(result);
                            return;
                        } else {
                            throw new RuntimeException("数据为空");
                        }
                    } else {
                        throw new RuntimeException(HttpRequestCode.ReturnCode(stateCode));
                    }
                }
            } catch (Exception e) {
                IOException ioException = new IOException(e.getMessage());
                retry = retryHandler.retryRequest(ioException, ++retryCount, httpContext);//把错误异常交给重试机制，以判断是否需要采取从事
                LogUtils.e(TAG, "重复次数：" + retryCount + "   :"+ e);
                if (!retry){
                    httpCallbackListener.onError(e);
                }
            }
        }
    }

    /**
     * http的返回结果的封装，可以直接从中获取返回的字符串或者流
     */
    public static class HttpResult {
        private HttpResponse mResponse;
        private InputStream mIn;
        private String mStr;
        private HttpClient mHttpClient;
        private HttpRequestBase mRequestBase;

        public HttpResult(HttpResponse response, HttpClient httpClient, HttpRequestBase requestBase) {
            mResponse = response;
            mHttpClient = httpClient;
            mRequestBase = requestBase;
        }

        public int getCode() {
            StatusLine status = mResponse.getStatusLine();
            return status.getStatusCode();
        }


        /**
         * 从结果中获取字符串，一旦获取，会自动关流，并且把字符串保存，方便下次获取
         */
        public String getString() {
            if (!StringUtils.isEmpty(mStr)) {
                return mStr;
            }
            InputStream inputStream = getInputStream();
            ByteArrayOutputStream out = null;
            if (inputStream != null) {
                try {
                    out = new ByteArrayOutputStream();
                    byte[] buffer = new byte[1024 * 4];
                    int len = -1;
                    while ((len = inputStream.read(buffer)) != -1) {
                        out.write(buffer, 0, len);
                    }
                    byte[] data = out.toByteArray();
                    mStr = new String(data, "utf-8");
                } catch (Exception e) {
                    LogUtils.e(TAG, e);
                } finally {
                    IOUtils.close(out);
                    close();
                }
            }
            return mStr;
        }

        /**
         * 获取流，需要使用完毕后调用close方法关闭网络连接
         */
        public InputStream getInputStream() {
            if (mIn == null && getCode() < 300) {
                HttpEntity entity = mResponse.getEntity();
                try {
                    mIn = entity.getContent();
                } catch (Exception e) {
                    LogUtils.e(TAG, e);
                }
            }
            return mIn;
        }

        /**
         * 关闭网络连接
         */
        public void close() {
            if (mRequestBase != null) {
                mRequestBase.abort();
            }
            IOUtils.close(mIn);
            if (mHttpClient != null) {
                mHttpClient.getConnectionManager().closeExpiredConnections();
            }
        }
    }
} public class ClassicRefreshHeaderView extends RelativeLayout implements RefreshTrigger {
    private ImageView ivArrow;

    private ImageView ivSuccess;

    private TextView tvRefresh;

    private ProgressBar progressBar;

    private Animation rotateUp;

    private Animation rotateDown;

    private boolean rotated = false;

    private int mHeight;

    public ClassicRefreshHeaderView(Context context) {
        this(context, null);
    }

    public ClassicRefreshHeaderView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ClassicRefreshHeaderView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        inflate(context, R.layout.layout_irecyclerview_classic_refresh_header_view, this);

        tvRefresh = (TextView) findViewById(R.id.tvRefresh);

        ivArrow = (ImageView) findViewById(R.id.ivArrow);

        ivSuccess = (ImageView) findViewById(R.id.ivSuccess);

        progressBar = (ProgressBar) findViewById(R.id.progressbar);

        rotateUp = AnimationUtils.loadAnimation(context, R.anim.rotate_up);

        rotateDown = AnimationUtils.loadAnimation(context, R.anim.rotate_down);
    }

    @Override
    public void onStart(boolean automatic, int headerHeight, int finalHeight) {
        this.mHeight = headerHeight;
        progressBar.setIndeterminate(false);
    }

    @Override
    public void onMove(boolean isComplete, boolean automatic, int moved) {
        if (!isComplete) {
            ivArrow.setVisibility(VISIBLE);
            progressBar.setVisibility(GONE);
            ivSuccess.setVisibility(GONE);
            if (moved <= mHeight) {
                if (rotated) {
                    ivArrow.clearAnimation();
                    ivArrow.startAnimation(rotateDown);
                    rotated = false;
                }

                tvRefresh.setText("SWIPE TO REFRESH");
            } else {
                tvRefresh.setText("RELEASE TO REFRESH");
                if (!rotated) {
                    ivArrow.clearAnimation();
                    ivArrow.startAnimation(rotateUp);
                    rotated = true;
                }
            }
        }
    }

    @Override
    public void onRefresh() {
        ivSuccess.setVisibility(GONE);
        ivArrow.clearAnimation();
        ivArrow.setVisibility(GONE);
        progressBar.setVisibility(VISIBLE);
        tvRefresh.setText("REFRESHING");
    }

    @Override
    public void onRelease() {

    }

    @Override
    public void onComplete() {
        rotated = false;
        ivSuccess.setVisibility(VISIBLE);
        ivArrow.clearAnimation();
        ivArrow.setVisibility(GONE);
        progressBar.setVisibility(GONE);
        tvRefresh.setText("COMPLETE");
    }

    @Override
    public void onReset() {
        rotated = false;
        ivSuccess.setVisibility(GONE);
        ivArrow.clearAnimation();
        ivArrow.setVisibility(GONE);
        progressBar.setVisibility(GONE);
    }
} public class DividerGridItemDecoration  extends RecyclerView.ItemDecoration
{

    private static final int[] ATTRS = new int[] { android.R.attr.listDivider };
    private Drawable mDivider;

    public DividerGridItemDecoration(Context context)
    {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, State state)
    {

        drawHorizontal(c, parent);
        drawVertical(c, parent);

    }

    private int getSpanCount(RecyclerView parent)
    {
        // 列数
        int spanCount = -1;
        LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager)
        {

            spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
        } else if (layoutManager instanceof StaggeredGridLayoutManager)
        {
            spanCount = ((StaggeredGridLayoutManager) layoutManager)
                    .getSpanCount();
        }
        return spanCount;
    }

    public void drawHorizontal(Canvas c, RecyclerView parent)
    {
        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++)
        {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getLeft() - params.leftMargin;
            final int right = child.getRight() + params.rightMargin
                    + mDivider.getIntrinsicWidth();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    public void drawVertical(Canvas c, RecyclerView parent)
    {
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++)
        {
            final View child = parent.getChildAt(i);

            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getTop() - params.topMargin;
            final int bottom = child.getBottom() + params.bottomMargin;
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicWidth();

            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    private boolean isLastColum(RecyclerView parent, int pos, int spanCount,
                                int childCount)
    {
        LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager)
        {
            if ((pos + 1) % spanCount == 0)// 如果是最后一列，则不需要绘制右边
            {
                return true;
            }
        } else if (layoutManager instanceof StaggeredGridLayoutManager)
        {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            if (orientation == StaggeredGridLayoutManager.VERTICAL)
            {
                if ((pos + 1) % spanCount == 0)// 如果是最后一列，则不需要绘制右边
                {
                    return true;
                }
            } else
            {
                childCount = childCount - childCount % spanCount;
                if (pos >= childCount)// 如果是最后一列，则不需要绘制右边
                    return true;
            }
        }
        return false;
    }

    private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,
                              int childCount)
    {
        LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager)
        {
            childCount = childCount - childCount % spanCount;
            if (pos >= childCount)// 如果是最后一行，则不需要绘制底部
                return true;
        } else if (layoutManager instanceof StaggeredGridLayoutManager)
        {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            // StaggeredGridLayoutManager 且纵向滚动
            if (orientation == StaggeredGridLayoutManager.VERTICAL)
            {
                childCount = childCount - childCount % spanCount;
                // 如果是最后一行，则不需要绘制底部
                if (pos >= childCount)
                    return true;
            } else
            // StaggeredGridLayoutManager 且横向滚动
            {
                // 如果是最后一行，则不需要绘制底部
                if ((pos + 1) % spanCount == 0)
                {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public void getItemOffsets(Rect outRect, int itemPosition,
                               RecyclerView parent)
    {
        int spanCount = getSpanCount(parent);
        int childCount = parent.getAdapter().getItemCount();
        if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行，则不需要绘制底部
        {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        } else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列，则不需要绘制右边
        {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else
        {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(),
                    mDivider.getIntrinsicHeight());
        }
    }
} public class LoadMoreFooterView extends FrameLayout {

    private Status mStatus;

    private View mLoadingView;

    private View mErrorView;

    private View mTheEndView;

    private OnRetryListener mOnRetryListener;

    public LoadMoreFooterView(Context context) {
        this(context, null);
    }

    public LoadMoreFooterView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LoadMoreFooterView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        LayoutInflater.from(context).inflate(R.layout.layout_irecyclerview_load_more_footer_view, this, true);

        mLoadingView = findViewById(R.id.loadingView);
        mErrorView = findViewById(R.id.errorView);
        mTheEndView = findViewById(R.id.theEndView);

        mErrorView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mOnRetryListener != null) {
                    mOnRetryListener.onRetry(LoadMoreFooterView.this);
                }
            }
        });

        setStatus(Status.GONE);
    }

    public void setOnRetryListener(OnRetryListener listener) {
        this.mOnRetryListener = listener;
    }

    public Status getStatus() {
        return mStatus;
    }

    public void setStatus(Status status) {
        this.mStatus = status;
        change();
    }

    public boolean canLoadMore() {
        return mStatus == Status.GONE || mStatus == Status.ERROR;
    }

    private void change() {
        switch (mStatus) {
            case GONE:
                mLoadingView.setVisibility(GONE);
                mErrorView.setVisibility(GONE);
                mTheEndView.setVisibility(GONE);
                break;

            case LOADING:
                mLoadingView.setVisibility(VISIBLE);
                mErrorView.setVisibility(GONE);
                mTheEndView.setVisibility(GONE);
                break;

            case ERROR:
                mLoadingView.setVisibility(GONE);
                mErrorView.setVisibility(VISIBLE);
                mTheEndView.setVisibility(GONE);
                break;

            case THE_END:
                mLoadingView.setVisibility(GONE);
                mErrorView.setVisibility(GONE);
                mTheEndView.setVisibility(VISIBLE);
                break;
        }
    }

    public enum Status {
        GONE, LOADING, ERROR, THE_END
    }

    public interface OnRetryListener {
        void onRetry(LoadMoreFooterView view);
    }

} public class LoadingPage extends FrameLayout {

    private final String TAG = LoadingPage.class.getSimpleName();

    private ResultState mCurrentState = ResultState.STATE_UNLOAD;// 当前状态

    private View mLoadingView;
    private View mErrorView;
    private View mEmptyView;
    private View mSuccessView;

    private Context mContext;
    private LoadingClickListener loadingClickListener;

    public LoadingPage(Context context) {
        this(context, null);
    }

    public LoadingPage(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LoadingPage(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
        initView();
    }

    /**
     * 初始化布局
     */
    private void initView() {
        // 正在加载
        if (mLoadingView == null) {
            mLoadingView = onCreateLoadingView();
            addView(mLoadingView);
        }

        // 加载失败
        if (mErrorView == null) {
            mErrorView = onCreateErrorView();
            // 点击重试
            mErrorView.findViewById(R.id.btn_retry).setOnClickListener(
                    new OnClickListener() {

                        @Override
                        public void onClick(View v) {
                            if (loadingClickListener != null) {
                                loadingClickListener.clickListener();
                            }
                        }
                    });
            addView(mErrorView);
        }

        // 数据为空
        if (mEmptyView == null) {
            mEmptyView = onCreateEmptyView();
            addView(mEmptyView);
        }

        showRightPage();
    }

    /**
     * 根据当前状态,展示正确页面
     */
    private void showRightPage() {
        if (mLoadingView != null) {
            mLoadingView
                    .setVisibility((mCurrentState == ResultState.STATE_LOADING || mCurrentState == ResultState.STATE_UNLOAD) ? View.VISIBLE
                            : View.GONE);
        }

        if (mEmptyView != null) {
            mEmptyView
                    .setVisibility(mCurrentState == ResultState.STATE_EMPTY ? View.VISIBLE
                            : View.GONE);
        }

        if (mErrorView != null) {
            mErrorView
                    .setVisibility(mCurrentState == ResultState.STATE_ERROR ? View.VISIBLE
                            : View.GONE);
        }

    }

    /**
     * 初始化正在加载布局
     */
    private View onCreateLoadingView() {

        return LayoutInflater.from(mContext).inflate(R.layout.page_loading, null);
    }

    /**
     * 初始化加载失败布局
     */
    private View onCreateErrorView() {
        return LayoutInflater.from(mContext).inflate(R.layout.page_error, null);
    }

    /**
     * 初始化数据为空布局
     */
    private View onCreateEmptyView() {
        return LayoutInflater.from(mContext).inflate(R.layout.page_empty, null);
    }

    public void setLoadingView(){
        setCurrentState(ResultState.STATE_LOADING);
        refreshView();
    }

    public void setErrorView(){
        setCurrentState(ResultState.STATE_ERROR);
        refreshView();
    }

    public void setEmptyView(){
        setCurrentState(ResultState.STATE_EMPTY);
        refreshView();
    }

    public void setSuccessView(){
        setCurrentState(ResultState.STATE_SUCCESS);
        refreshView();
    }

    public void setLoadingClickListener(LoadingClickListener buttonClickListener) {
        this.loadingClickListener = buttonClickListener;
    }

    public void setCurrentState(ResultState currentState) {
        this.mCurrentState = currentState;
    }

    public ResultState getCurrentState() {
        return mCurrentState;
    }

    public void refreshView() {
        mCurrentState = getCurrentState();
        showRightPage();
    }

    /**
     * 使用枚举表示访问网络的几种状态
     */
    public enum ResultState {
        STATE_UNLOAD,    // 尚未开始加载数据的时候
        STATE_LOADING,    // 正在加载数据
        STATE_SUCCESS, // 访问成功
        STATE_EMPTY, // 数据为空
        STATE_ERROR;// 访问失败
    }

    public interface LoadingClickListener {
        void clickListener();
    }

}
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import com.aspsine.irecyclerview.IRecyclerView;
import com.aspsine.irecyclerview.OnLoadMoreListener;
import com.aspsine.irecyclerview.OnRefreshListener;
import java.util.ArrayList;
import java.util.List;
import cn.bproject.neteasynews.MyApplication;
import cn.bproject.neteasynews.R;
import cn.bproject.neteasynews.Utils.DensityUtils;
import cn.bproject.neteasynews.Utils.LocalCacheUtils;
import cn.bproject.neteasynews.Utils.LogUtils;
import cn.bproject.neteasynews.Utils.NetWorkUtil;
import cn.bproject.neteasynews.Utils.ThreadManager;
import cn.bproject.neteasynews.Utils.ToastUtils;
import cn.bproject.neteasynews.activity.PicDetailActivity;
import cn.bproject.neteasynews.adapter.PicListAdapter;
import cn.bproject.neteasynews.bean.PicListBean;
import cn.bproject.neteasynews.common.Api;
import cn.bproject.neteasynews.common.DefineView;
import cn.bproject.neteasynews.fragment.BaseFragment;
import cn.bproject.neteasynews.http.DataParse;
import cn.bproject.neteasynews.http.HttpCallbackListener;
import cn.bproject.neteasynews.http.HttpHelper;
import cn.bproject.neteasynews.widget.ClassicRefreshHeaderView;
import cn.bproject.neteasynews.widget.DividerGridItemDecoration;
import cn.bproject.neteasynews.widget.LoadMoreFooterView;
import cn.bproject.neteasynews.widget.LoadingPage;
                case HANDLER_SHOW_ERROR:
                    error = (String) message.obj;
                    ToastUtils.showShort(error);
                    // 如果有缓存内容就不展示错误页面
                    if (!isShowCache) {
                        showErroPage();
                    }
                    break;
                case HANDLER_SHOW_REFRESH_LOADMORE:
                    result = (String) message.obj;
                    newlist = DataParse.PicList(result);
                    DataChange();
                    isConnectState = false;
                    break;
                case HANDLER_SHOW_REFRESH_LOADMORE_ERRO:
                    error = (String) message.obj;
                    ToastUtils.showShort(error);
                    mIRecyclerView.setRefreshing(false);
                    mLoadMoreFooterView.setStatus(LoadMoreFooterView.Status.ERROR);
                    isConnectState = false;
                    break;
            }
            return false;
        }
    });


    public static PicListFragment newInstance(String tid, String column) {
        Bundle bundle = new Bundle();
        bundle.putSerializable(KEY_TID, tid);
        bundle.putSerializable(KEY_COLUMN, column);
        PicListFragment fragment = new PicListFragment();
        fragment.setArguments(bundle);
        return fragment;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mView = inflater.inflate(R.layout.fragment_pic_list, container, false);

        initView();
        initValidata();
        initListener();
        return mView;
    }


    @Override
    public void initView() {

        mLoadingPage = (LoadingPage) mView.findViewById(R.id.loading_page);
        mIRecyclerView = (IRecyclerView) mView.findViewById(R.id.iRecyclerView);
        mIRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 1));
        mIRecyclerView.addItemDecoration(new DividerGridItemDecoration(getActivity()));
        mLoadMoreFooterView = (LoadMoreFooterView) mIRecyclerView.getLoadMoreFooterView();
        ClassicRefreshHeaderView classicRefreshHeaderView = new ClassicRefreshHeaderView(getActivity());
        classicRefreshHeaderView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, DensityUtils.dip2px(getActivity(), 80)));
        // we can set view
        mIRecyclerView.setRefreshHeaderView(classicRefreshHeaderView);
        showLoadingPage();
    }

    @Override
    public void initValidata() {
        if (getArguments() != null) {
            //取出保存的频道TID
            tid = getArguments().getString(KEY_TID);
            column = getArguments().getString(KEY_COLUMN);
        }
        mThreadPool = ThreadManager.getThreadPool();

        mUrl = Api.PictureUrl + tid + column + mStartIndex + Api.endPicture;
        getNewsFromCache();

    }

    /**
     * 从缓存中读取并解析显示数据
     */
    private void getNewsFromCache() {
        mThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                String cache = LocalCacheUtils.getLocalCache(mUrl);
                if (!TextUtils.isEmpty(cache)) {
                    mPicListBeens = DataParse.PicList(cache);
                    if (mPicListBeens != null) {
                        LogUtils.d(TAG, "读取缓存成功");
                        isShowCache = true;
                        Message message = mHandler.obtainMessage();
                        message.what = HANDLER_SHOW_NEWS;
                        mHandler.sendMessage(message);
                    } else {
                        isShowCache = false;
                    }
                }
                if (!isLastNews(tid) || TextUtils.isEmpty(cache)) {
                    if (NetWorkUtil.isNetworkConnected(getActivity())) {
                        // 有网络的情况下请求网络数据
                        requestData();
                    } else {
                        sendErrorMessage(HANDLER_SHOW_ERROR, "没有网络");
                    }
                }

            }
        });
    }


    public void requestData() {

//        http://pic.news.163.com/photocenter/api/list/0003/00AJ0003,0AJQ0003,3LF60003,00B70003,00B50003//0/20.json
        if (!isConnectState) {
            mThreadPool.execute(new Runnable() {
                @Override
                public void run() {

                    mUrl = Api.PictureUrl + tid + column + mStartIndex + Api.endPicture;
                    HttpHelper.get(mUrl, new HttpCallbackListener() {