月考模擬

一些依賴

compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.facebook.fresco:fresco:0.12.0'

compile 'io.reactivex:rxandroid:1.0.1'
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
compile 'com.squareup.retrofit2:converter-scalars:+'
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
android:name=".App"
<activity android:name=".PicActivity"></activity>

    drawable

ic_launcher_background.xml

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportHeight="108"
    android:viewportWidth="108">
    <path
        android:fillColor="#26A69A"
        android:pathData="M0,0h108v108h-108z" />
    <path
        android:fillColor="#00000000"
        android:pathData="M9,0L9,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,0L19,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M29,0L29,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M39,0L39,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M49,0L49,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M59,0L59,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M69,0L69,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M79,0L79,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M89,0L89,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M99,0L99,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,9L108,9"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,19L108,19"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,29L108,29"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,39L108,39"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,49L108,49"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,59L108,59"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,69L108,69"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,79L108,79"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,89L108,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,99L108,99"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,29L89,29"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,39L89,39"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,49L89,49"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,59L89,59"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,69L89,69"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,79L89,79"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M29,19L29,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M39,19L39,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M49,19L49,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M59,19L59,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M69,19L69,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
    <path
        android:fillColor="#00000000"
        android:pathData="M79,19L79,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8" />
</vector>


   activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
   >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#28B8F7">

        <RelativeLayout
            android:layout_width="50dp"
            android:layout_height="match_parent">

            <ImageView
                android:id="@+id/image_left"
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:src="@drawable/left"
                android:layout_centerInParent="true"/>

        </RelativeLayout>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent">

            <TextView
                android:id="@+id/bzbm"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:layout_height="match_parent"
                android:text="報紙版面"
                android:textColor="#FFFFFF"
                android:textSize="18sp"
                android:layout_marginRight="5dp"
                android:gravity="center_vertical|right"/>

            <TextView
                android:id="@+id/bqml"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:layout_height="match_parent"
                android:text="本期目錄"
                android:textColor="#FFFFFF"
                android:textSize="18sp"
                android:layout_marginLeft="5dp"
                android:gravity="center_vertical|left"/>

        </LinearLayout>

        <RelativeLayout
            android:layout_width="50dp"
            android:layout_height="match_parent">

            <ImageView
                android:id="@+id/image_right"
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:src="@drawable/right"
                android:layout_centerInParent="true"/>

        </RelativeLayout>

    </LinearLayout>

    <FrameLayout
        android:id="@+id/frame_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </FrameLayout>

</LinearLayout>

   activity_pic.xml


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
   >


    <android.support.v4.view.ViewPager
        android:layout_centerInParent="true"
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </android.support.v4.view.ViewPager>

</RelativeLayout>

fragment_bqml.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#FFFFFF">

        <TextView
            android:id="@+id/date"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:layout_marginLeft="5dp"
            android:textColor="#28B8F7"
            android:textSize="18dp"
            android:gravity="center_vertical"/>

        <TextView
            android:id="@+id/mldh"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_alignParentRight="true"
            android:gravity="center_vertical"
            android:layout_marginRight="5dp"
            android:textColor="#28B8F7"
            android:textSize="18dp"
            android:text="目錄導航"/>

    </RelativeLayout>

    <ExpandableListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:groupIndicator="@null">

    </ExpandableListView>

</LinearLayout>

  fragment_bzbm.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/date"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginLeft="5dp"
        android:textColor="#28B8F7"
        android:textSize="18dp"
        android:background="#FFFFFF"
        android:gravity="center_vertical"/>

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </android.support.v4.view.ViewPager>

</LinearLayout>

   layout_child.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/child_title"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:gravity="center_vertical"
        android:layout_marginLeft="20dp"/>

</LinearLayout>

   layout_group.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:gravity="center_vertical"
        android:background="#CCCCCC">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="30dp"
            android:src="@drawable/group"
            android:layout_marginLeft="10dp"/>

        <TextView
            android:id="@+id/group_name"
            android:layout_width="wrap_content"
            android:layout_height="100dp"
            android:gravity="center_vertical"
            android:layout_marginLeft="10dp"/>

    </LinearLayout>

</LinearLayout>


mldh.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <ListView
        android:id="@+id/list_view"
        android:layout_width="150dp"
        android:layout_height="wrap_content"
        android:background="#999999"
        android:alpha="0.7">

    </ListView>

</LinearLayout>


 

MainActivity.java
package com.example.dasd.yuekao1;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.dasd.yuekao1.fragment.BQML;
import com.example.dasd.yuekao1.fragment.BZBM;
import com.example.dasd.yuekao1.model.DataDataBean;
import com.example.dasd.yuekao1.util.Api;
import com.example.dasd.yuekao1.util.RetrofitHelper;
import com.google.gson.Gson;

import java.util.ArrayList;
import java.util.List;

import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private ImageView image_left;
    private TextView bzbm;
    private TextView bqml;
    private ImageView image_right;
    private FrameLayout frame_layout;
    private String str;
    private ArrayList<String> imageUrls;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        hideActionBar();

        switchFragment(0);

        RetrofitHelper.getApiService(Api.BASE_URL)
                .getData(Api.URL, Api.getParams())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        imageUrls = new ArrayList<>();
                        Gson gson = new Gson();
                        DataDataBean dataDataBean = gson.fromJson(s, DataDataBean.class);
                        List<DataDataBean.LayoutsBean> layouts = dataDataBean.getLayouts();
                        for (int i = 0; i < layouts.size(); i++) {
                            imageUrls.add(layouts.get(i).getPicUrl());
                        }
                    }
                });
    }

    private void switchFragment(int index) {
        switch (index) {
            case 0:
                getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout, new BZBM()).commit();
                break;
            case 1:
                getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout, new BQML()).commit();
                break;
            default:
                break;
        }
    }

    private void hideActionBar() {
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.hide();
        }
    }

    private void initView() {
        image_left = (ImageView) findViewById(R.id.image_left);
        bzbm = (TextView) findViewById(R.id.bzbm);
        bqml = (TextView) findViewById(R.id.bqml);
        image_right = (ImageView) findViewById(R.id.image_right);
        frame_layout = (FrameLayout) findViewById(R.id.frame_layout);

        image_left.setOnClickListener(this);
        bzbm.setOnClickListener(this);
        bqml.setOnClickListener(this);
        image_right.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.image_left:
                str.contains("error");
                break;
            case R.id.bzbm:
                switchFragment(0);
                break;
            case R.id.bqml:
                switchFragment(1);
                break;
            case R.id.image_right:
                Intent intent = new Intent(MainActivity.this, PicActivity.class);
                intent.putStringArrayListExtra("list", imageUrls);
                startActivity(intent);
                break;
            default:
                break;
        }
    }
}
             

            App.java
package com.example.dasd.yuekao1;

import android.app.Application;

import com.example.dasd.yuekao1.util.CrashHandler;
import com.example.dasd.yuekao1.util.ImagePipelineConfigUtils;
import com.facebook.drawee.backends.pipeline.Fresco;

/**
 * Created by yujie on 2018/1/18.
 */

public class App extends Application{
    @Override
    public void onCreate() {
        super.onCreate();
        Fresco.initialize(this, ImagePipelineConfigUtils.getDefaultImagePipelineConfig(this));
        CrashHandler.getInstace().init(this);
    }
}

PicActivity.java
package com.example.dasd.yuekao1;

import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;

import com.bumptech.glide.Glide;

import java.util.ArrayList;

public class PicActivity extends AppCompatActivity {
    private ViewPager viewPager;
    private ArrayList<String> imageUrls;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pic);

        hideActionBar();

        viewPager = (ViewPager) findViewById(R.id.view_pager);

        //獲取導數據
        imageUrls = getIntent().getStringArrayListExtra("list");

        if (imageUrls != null){
            viewPager.setAdapter(new PagerAdapter() {
                @Override
                public Object instantiateItem(ViewGroup container, int position) {
                    ZoomImageView imageView = new ZoomImageView(PicActivity.this);
                    //加載圖片顯示
                    Glide.with(PicActivity.this).load(imageUrls.get(position)).into(imageView);

                    //添加
                    container.addView(imageView);
                    //返回
                    return imageView;
                }

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

                @Override
                public boolean isViewFromObject(View arg0, Object arg1) {
                    return arg0 == arg1;
                }

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

    }

    private void hideActionBar() {
       ActionBar actionBar = getSupportActionBar();
       if (actionBar != null) {
          actionBar.hide();
       }
    }

}

           ZoomImageView.java
package com.example.dasd.yuekao1;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.ImageView;

@SuppressLint("AppCompatCustomView")
public class ZoomImageView extends ImageView implements OnGlobalLayoutListener, OnScaleGestureListener, OnTouchListener {

    private boolean mOnce;

    /**
     * 初始化時縮放的值
     */
    private float mInitScale;

    /**
     * 雙擊放大值到達的值
     */
    private float mMidScale;

    /**
     * 放大的最大值
     */
    private float mMaxScale;

    private Matrix mScaleMatrix;

    /**
     * 捕獲用戶多指觸控時縮放的比例
     */
    private ScaleGestureDetector mScaleGestureDetector;

    // **********自由移動的變量***********
    /**
     * 記錄上一次多點觸控的數量
     */
    private int mLastPointerCount;

    private float mLastX;
    private float mLastY;

    private int mTouchSlop;
    private boolean isCanDrag;

    private boolean isCheckLeftAndRight;
    private boolean isCheckTopAndBottom;

    // *********雙擊放大與縮小*********
    private GestureDetector mGestureDetector;

    private boolean isAutoScale;

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

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

    public ZoomImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // init
        mScaleMatrix = new Matrix();
        setScaleType(ScaleType.MATRIX);
        setOnTouchListener(this);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        mScaleGestureDetector = new ScaleGestureDetector(context, this);
        mGestureDetector = new GestureDetector(context,
                new GestureDetector.SimpleOnGestureListener() {
                    @Override
                    public boolean onDoubleTap(MotionEvent e) {

                        if (isAutoScale) {
                            return true;
                        }

                        float x = e.getX();
                        float y = e.getY();

                        if (getScale() < mMidScale) {
                            postDelayed(new AutoScaleRunnable(mMidScale, x, y), 16);
                            isAutoScale = true;
                        } else {
                            postDelayed(new AutoScaleRunnable(mInitScale, x, y), 16);
                            isAutoScale = true;
                        }
                        return true;
                    }
                });
    }

    /**
     * 自動放大與縮小
     *
     * @author [email protected]
     *
     */
    private class AutoScaleRunnable implements Runnable {
        /**
         * 縮放的目標值
         */
        private float mTargetScale;
        // 縮放的中心點
        private float x;
        private float y;

        private final float BIGGER = 1.07f;
        private final float SMALL = 0.93f;

        private float tmpScale;

        /**
         * @param mTargetScale
         * @param x
         * @param y
         */
        public AutoScaleRunnable(float mTargetScale, float x, float y) {
            this.mTargetScale = mTargetScale;
            this.x = x;
            this.y = y;

            if (getScale() < mTargetScale) {
                tmpScale = BIGGER;
            }
            if (getScale() > mTargetScale) {
                tmpScale = SMALL;
            }
        }

        @Override
        public void run() {
            //進行縮放
            mScaleMatrix.postScale(tmpScale, tmpScale, x, y);
            checkBorderAndCenterWhenScale();
            setImageMatrix(mScaleMatrix);

            float currentScale = getScale();

            if ((tmpScale >1.0f && currentScale <mTargetScale) ||(tmpScale<1.0f &&currentScale>mTargetScale)) {
                //這個方法是重新調用run()方法
                postDelayed(this, 16);
            }else{
                //設置爲我們的目標值
                float scale = mTargetScale/currentScale;
                mScaleMatrix.postScale(scale, scale, x, y);
                checkBorderAndCenterWhenScale();
                setImageMatrix(mScaleMatrix);

                isAutoScale = false;
            }
        }
    }

    /**
     * 獲取ImageView加載完成的圖片
     */
    @Override
    public void onGlobalLayout() {
        if (!mOnce) {
            // 得到控件的寬和高
            int width = getWidth();
            int height = getHeight();

            // 得到我們的圖片,以及寬和高
            Drawable drawable = getDrawable();
            if (drawable == null) {
                return;
            }
            int dh = drawable.getIntrinsicHeight();
            int dw = drawable.getIntrinsicWidth();

            float scale = 0.5f;

            // 圖片的寬度大於控件的寬度,圖片的高度小於空間的高度,我們將其縮小
            if (dw > width && dh < height) {
                scale = width * 1.0f / dw;
            }

            // 圖片的寬度小於控件的寬度,圖片的高度大於空間的高度,我們將其縮小
            if (dh > height && dw < width) {
                scale = height * 1.0f / dh;
            }

            // 縮小值
            if (dw > width && dh > height) {
                scale = Math.min(width * 1.0f / dw, height * 1.0f / dh);
            }

            // 放大值
            if (dw < width && dh < height) {
                scale = Math.min(width * 1.0f / dw, height * 1.0f / dh);
            }

            /**
             * 得到了初始化時縮放的比例
             */
            mInitScale = scale;
            mMaxScale = mInitScale * 4;
            mMidScale = mInitScale * 2;

            // 將圖片移動至控件的中間
            int dx = getWidth() / 2 - dw / 2;
            int dy = getHeight() / 2 - dh / 2;

            mScaleMatrix.postTranslate(dx, dy);
            mScaleMatrix.postScale(mInitScale, mInitScale, width / 2,
                    height / 2);
            setImageMatrix(mScaleMatrix);

            mOnce = true;
        }
    }

    /**
     * 註冊OnGlobalLayoutListener這個接口
     */
    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        getViewTreeObserver().addOnGlobalLayoutListener(this);
    }

    /**
     * 取消OnGlobalLayoutListener這個接口
     */
    @SuppressWarnings("deprecation")
    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        getViewTreeObserver().removeGlobalOnLayoutListener(this);
    }

    /**
     * 獲取當前圖片的縮放值
     *
     * @return
     */
    public float getScale() {
        float[] values = new float[9];
        mScaleMatrix.getValues(values);
        return values[Matrix.MSCALE_X];
    }

    // 縮放區間時initScale maxScale
    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        float scale = getScale();
        float scaleFactor = detector.getScaleFactor();

        if (getDrawable() == null) {
            return true;
        }

        // 縮放範圍的控制
        if ((scale < mMaxScale && scaleFactor > 1.0f)
                || (scale > mInitScale && scaleFactor < 1.0f)) {
            if (scale * scaleFactor < mInitScale) {
                scaleFactor = mInitScale / scale;
            }

            if (scale * scaleFactor > mMaxScale) {
                scale = mMaxScale / scale;
            }

            // 縮放
            mScaleMatrix.postScale(scaleFactor, scaleFactor,
                    detector.getFocusX(), detector.getFocusY());

            checkBorderAndCenterWhenScale();

            setImageMatrix(mScaleMatrix);
        }

        return true;
    }

    /**
     * 獲得圖片放大縮小以後的寬和高,以及left,right,top,bottom
     *
     * @return
     */
    private RectF getMatrixRectF() {
        Matrix matrix = mScaleMatrix;
        RectF rectF = new RectF();
        Drawable d = getDrawable();
        if (d != null) {
            rectF.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
            matrix.mapRect(rectF);
        }
        return rectF;
    }

    /**
     * 在縮放的時候進行邊界以及我們的位置的控制
     */
    private void checkBorderAndCenterWhenScale() {
        RectF rectF = getMatrixRectF();
        float deltaX = 0;
        float deltaY = 0;

        int width = getWidth();
        int height = getHeight();

        // 縮放時進行邊界檢測,防止出現白邊
        if (rectF.width() >= width) {
            if (rectF.left > 0) {
                deltaX = -rectF.left;
            }
            if (rectF.right < width) {
                deltaX = width - rectF.right;
            }
        }

        if (rectF.height() >= height) {
            if (rectF.top > 0) {
                deltaY = -rectF.top;
            }
            if (rectF.bottom < height) {
                deltaY = height - rectF.bottom;
            }
        }

        /**
         * 如果寬度或高度小於空間的寬或者高,則讓其居中
         */
        if (rectF.width() < width) {
            deltaX = width / 2f - rectF.right + rectF.width() / 2f;
        }

        if (rectF.height() < height) {
            deltaY = height / 2f - rectF.bottom + rectF.height() / 2f;
        }

        mScaleMatrix.postTranslate(deltaX, deltaY);
    }

    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {

        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {

    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        if (mGestureDetector.onTouchEvent(event)) {
            return true;
        }

        mScaleGestureDetector.onTouchEvent(event);

        float x = 0;
        float y = 0;
        // 拿到多點觸控的數量
        int pointerCount = event.getPointerCount();
        for (int i = 0; i < pointerCount; i++) {
            x += event.getX(i);
            y += event.getY(i);
        }

        x /= pointerCount;
        y /= pointerCount;

        if (mLastPointerCount != pointerCount) {
            isCanDrag = false;
            mLastX = x;
            mLastY = y;
        }
        mLastPointerCount = pointerCount;
        RectF rectF = getMatrixRectF();
        switch (event.getAction()) {

            case MotionEvent.ACTION_DOWN:
                if (rectF.width()>getWidth() +0.01|| rectF.height()>getHeight()+0.01) {
                    if(getParent() instanceof ViewPager)
                        getParent().requestDisallowInterceptTouchEvent(true);
                }
                break;

            case MotionEvent.ACTION_MOVE:
                if (rectF.width()>getWidth()+0.01 || rectF.height()>getHeight()+0.01) {
                    if(getParent() instanceof ViewPager){
                        Log.e("---","----+++");
                        getParent().requestDisallowInterceptTouchEvent(true);
                    }
                }
                float dx = x - mLastX;
                float dy = y - mLastY;

                if (!isCanDrag) {
                    isCanDrag = isMoveAction(dx, dy);
                }

                if (isCanDrag) {
                    if (getDrawable() != null) {
                        isCheckLeftAndRight = isCheckTopAndBottom = true;
                        // 如果寬度小於控件寬度,不允許橫向移動
                        if (rectF.width() < getWidth()) {
                            isCheckLeftAndRight = false;
                            dx = 0;
                        }
                        // 如果高度小於控件高度,不允許縱向移動
                        if (rectF.height() < getHeight()) {
                            isCheckTopAndBottom = false;
                            dy = 0;
                        }
                        mScaleMatrix.postTranslate(dx, dy);

                        checkBorderWhenTranslate();

                        setImageMatrix(mScaleMatrix);
                    }
                }
                mLastX = x;
                mLastY = y;
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mLastPointerCount = 0;
                break;

            default:
                break;
        }

        return true;
    }

    /**
     * 當移動時進行邊界檢查
     */
    private void checkBorderWhenTranslate() {
        RectF rectF = getMatrixRectF();
        float deltaX = 0;
        float deltaY = 0;

        int width = getWidth();
        int heigth = getHeight();

        if (rectF.top > 0 && isCheckTopAndBottom) {
            deltaY = -rectF.top;
        }
        if (rectF.bottom < heigth && isCheckTopAndBottom) {
            deltaY = heigth - rectF.bottom;
        }
        if (rectF.left > 0 && isCheckLeftAndRight) {
            deltaX = -rectF.left;
        }
        if (rectF.right < width && isCheckLeftAndRight) {
            deltaX = width - rectF.right;
        }
        mScaleMatrix.postTranslate(deltaX, deltaY);

    }

    /**
     * 判斷是否是move
     *
     * @param dx
     * @param dy
     * @return
     */
    private boolean isMoveAction(float dx, float dy) {
        return Math.sqrt(dx * dx + dy * dy) > mTouchSlop;
    }
}

base包
BaseActivity.java
package com.example.dasd.yuekao1.base;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;

public abstract class BaseActivity<IPre, P extends BasePresenter<IPre>> extends AppCompatActivity{
    public P presenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(setLayoutResID());

        presenter = initPresenter();

        presenter.attach((IPre) this);

        initView();

        initData();
    }

    public abstract int setLayoutResID();

    public abstract P initPresenter();

    public abstract void initView();

    public abstract void initData();
}

base包
BaseFragment.java
package com.example.dasd.yuekao1.base;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public abstract class BaseFragment<IPre, P extends BasePresenter<IPre>> extends Fragment{
    public P presenter;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return createView(inflater, container, savedInstanceState);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        presenter = initPresenter();
        presenter.attach((IPre) this);

        initData();
    }

    protected abstract View createView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);

    protected abstract P initPresenter();

    protected abstract void initData();
}

base包
BasePresenter.java
package com.example.dasd.yuekao1.base;

public abstract class BasePresenter<IPre> {
    public IPre iPresenter;

    public void attach(IPre iPresenter){
        this.iPresenter = iPresenter;
      initModel();
    }

    public void detach(){
        if(iPresenter != null){
            iPresenter = null;
        }
    }

    protected abstract void initModel();
}

fragment包
BQML.java

package com.example.dasd.yuekao1.fragment;

import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;

import com.example.dasd.yuekao1.R;
import com.example.dasd.yuekao1.base.BaseFragment;
import com.example.dasd.yuekao1.model.DataDataBean;
import com.example.dasd.yuekao1.presenter.IPresenter;
import com.example.dasd.yuekao1.presenter.PresenterImpl;
import com.example.dasd.yuekao1.util.Api;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by yujie on 2018/1/18.
 */

public class BQML extends BaseFragment<IPresenter, PresenterImpl> implements IPresenter, View.OnClickListener {

    private TextView date_text;
    private TextView mldh;
    private ExpandableListView listView;
    private List<DataDataBean.LayoutsBean> layouts;
    private PopupWindow popupWindow;
    private List<String> dhs;

    @Override
    protected View createView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_bqml, container, false);
        initView(view);
        return view;
    }

    private void initView(View view) {
        date_text = (TextView) view.findViewById(R.id.date);
        mldh = (TextView) view.findViewById(R.id.mldh);
        listView = (ExpandableListView) view.findViewById(R.id.list_view);

        mldh.setOnClickListener(this);
        listView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView expandableListView, View view, int i, int i1, long l) {
                Toast.makeText(getContext(), layouts.get(i).getList().get(i1).getTitle(), Toast.LENGTH_SHORT).show();
                return false;
            }
        });
    }

    @Override
    protected PresenterImpl initPresenter() {
        return new PresenterImpl();
    }

    @Override
    protected void initData() {
        presenter.getData(Api.BASE_URL, Api.URL, Api.getParams());
    }

    @Override
    public void onPreSuccess(DataDataBean dataDataBean) {
        dhs = new ArrayList<>();
        date_text.setText(dataDataBean.getDate());
        layouts = dataDataBean.getLayouts();
        listView.setAdapter(new ELAdapter());
        for (int i = 0; i < layouts.size(); i++) {
            dhs.add(layouts.get(i).getName());
            listView.expandGroup(i);
        }
    }

    @Override
    public void onPreError() {

    }

    @Override
    public void onClick(View view) {
        View view1 = LayoutInflater.from(getContext()).inflate(R.layout.mldh, null, false);
        ListView list = (ListView) view1.findViewById(R.id.list_view);
        list.setAdapter(new ArrayAdapter<String>(getContext(), android.R.layout.simple_list_item_1, dhs));
        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                listView.setSelectedGroup(i);
                popupWindow.dismiss();
            }
        });
        popupWindow = new PopupWindow(view1,
                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        popupWindow.setFocusable(true);
        popupWindow.setBackgroundDrawable(new BitmapDrawable());
        popupWindow.setOutsideTouchable(true);
        popupWindow.showAsDropDown(mldh);
    }

    class ELAdapter extends BaseExpandableListAdapter{


        @Override
        public int getGroupCount() {
            return layouts.size();
        }

        @Override
        public int getChildrenCount(int i) {
            return layouts.get(i).getList().size();
        }

        @Override
        public Object getGroup(int i) {
            return layouts.get(i);
        }

        @Override
        public Object getChild(int i, int i1) {
            return layouts.get(i).getList().get(i1).getTitle();
        }

        @Override
        public long getGroupId(int i) {
            return i;
        }

        @Override
        public long getChildId(int i, int i1) {
            return i1;
        }

        @Override
        public boolean hasStableIds() {
            return false;
        }

        @Override
        public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) {
            GroupViewHolder holder;
            if(view == null){
                view = View.inflate(getContext(), R.layout.layout_group, null);
                holder = new GroupViewHolder();
                holder.group_name = (TextView) view.findViewById(R.id.group_name);
                view.setTag(holder);
            }else{
                holder = (GroupViewHolder) view.getTag();
            }

            holder.group_name.setText(layouts.get(i).getName());

            return view;
        }

        @Override
        public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup) {
            ChildViewHolder holder;
            if(view == null){
                view = View.inflate(getContext(), R.layout.layout_child, null);
                holder = new ChildViewHolder();
                holder.child_title = (TextView) view.findViewById(R.id.child_title);
                view.setTag(holder);
            }else{
                holder = (ChildViewHolder) view.getTag();
            }

            holder.child_title.setText(layouts.get(i).getList().get(i1).getTitle());

            return view;
        }

        @Override
        public boolean isChildSelectable(int i, int i1) {
            return true;
        }

        class GroupViewHolder{
            TextView group_name;
        }

        class ChildViewHolder{
            TextView child_title;
        }
    }
}


fragment包
BZBM.java
package com.example.dasd.yuekao1.fragment;

import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.example.dasd.yuekao1.R;
import com.example.dasd.yuekao1.base.BaseFragment;
import com.example.dasd.yuekao1.model.DataDataBean;
import com.example.dasd.yuekao1.presenter.IPresenter;
import com.example.dasd.yuekao1.presenter.PresenterImpl;
import com.example.dasd.yuekao1.util.Api;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.backends.pipeline.PipelineDraweeController;
import com.facebook.drawee.drawable.ScalingUtils;
import com.facebook.drawee.generic.GenericDraweeHierarchy;
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
import com.facebook.drawee.view.SimpleDraweeView;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;

import java.util.List;

/**
 * Created by yujie on 2018/1/18.
 */

public class BZBM extends BaseFragment<IPresenter, PresenterImpl> implements IPresenter {

    private TextView date_text;
    private ViewPager viewPager;
    private List<DataDataBean.LayoutsBean> layouts;

    @Override
    protected View createView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_bzbm, container, false);
        initView(view);
        return view;
    }

    private void initView(View view) {
        date_text = (TextView) view.findViewById(R.id.date);
        viewPager = (ViewPager) view.findViewById(R.id.view_pager);
    }

    @Override
    protected PresenterImpl initPresenter() {
        return new PresenterImpl();
    }

    @Override
    protected void initData() {
        presenter.getData(Api.BASE_URL, Api.URL, Api.getParams());
    }

    @Override
    public void onPreSuccess(DataDataBean dataDataBean) {
        layouts = dataDataBean.getLayouts();
        date_text.setText(dataDataBean.getDate());
        viewPager.setAdapter(new VPAdapter());
    }

    @Override
    public void onPreError() {

    }

    class VPAdapter extends PagerAdapter{

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

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

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            SimpleDraweeView simpleDraweeView = new SimpleDraweeView(getActivity());
            simpleDraweeView.setAspectRatio((float) 1);
            //使用控件,並添加到佈局中
            // 圖片的地址
            Uri uri = Uri.parse(layouts.get(position).getPicUrl());
            // 圖片的請求
            ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
                    .build();
            // 加載圖片的控制
            PipelineDraweeController controller = (PipelineDraweeController) Fresco.newDraweeControllerBuilder()
                    .setOldController(simpleDraweeView.getController())
                    .setImageRequest(request)
                    .build();
            simpleDraweeView.setBackgroundColor(Color.WHITE);
            GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(getResources());
            GenericDraweeHierarchy FIT_XY = builder.setActualImageScaleType(ScalingUtils.ScaleType.FIT_XY).build();
            simpleDraweeView.setHierarchy(FIT_XY);
            // 加載圖片
            simpleDraweeView.setController(controller);
            container.addView(simpleDraweeView);
            return simpleDraweeView;
        }

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

}

model包
DataDataBean.java
package com.example.dasd.yuekao1.model;

import java.util.List;

/**
 * Created by yujie on 2018/1/18.
 */

public class DataDataBean {

    /**
     * version : 0
     * layouts : [{"id":225823,"name":"旅遊報01版","date":"2017-08-30","picUrl":"https://img.newaircloud.com/xkycs/paper/201708/30/d9f405e7-2a7e-4459-a6e9-324e41f31927.jpg","height":2009,"width":1259,"mapping":[{"mapping":["66.617056%,82.362460%","98.118145%,82.362460%","98.118145%,66.181230%","66.617056%,66.181230%"],"articleID":"2228451"},{"mapping":["1.807440%,79.288026%","63.776794%,79.288026%","63.776794%,58.899676%","1.807440%,58.899676%"],"articleID":"2228452"},{"mapping":["67.649879%,63.430421%","97.085322%,63.430421%","97.085322%,49.029126%","67.649879%,49.029126%"],"articleID":"2228453"},{"mapping":["97.085322%,47.087379%","67.649879%,47.087379%","67.649879%,36.245955%","67.649879%,35.436893%","67.649879%,35.436893%","67.649879%,28.640777%","74.621431%,28.640777%","75.137842%,27.993528%","75.137842%,22.977346%","89.597359%,22.977346%","89.597359%,27.993528%","97.085322%,28.802589%"],"articleID":"2228454"},{"mapping":["1.807440%,54.045307%","64.035000%,54.045307%","64.035000%,17.961165%","1.807440%,17.961165%"],"articleID":"2228455"},{"mapping":["58.096270%,15.210356%","98.118145%,15.210356%","98.118145%,2.103560%","58.096270%,2.103560%"],"articleID":"2228456"}],"list":[{"id":2228451,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228451.json?v=1504073111","title":"醫療旅遊服務產業成重要方向","version":1504073111,"pic1":""},{"id":2228452,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228452.json?v=1504073111","title":"內蒙古以全域旅遊之筆繪行業發展藍圖","version":1504073111,"pic1":""},{"id":2228453,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228453.json?v=1504073112","title":"城市旅遊","version":1504073112,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/baa4058e-d021-4e6a-b515-d1631976a5b1.jpg"},{"id":2228454,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228454.json?v=1504073113","title":"大詞彙文化旅遊","version":1504073113,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/715b3468-93ef-4e60-8730-ec00a2002de0.jpg"},{"id":2228455,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228455.json?v=1504073115","title":"澳大利亞全國旅遊會議首次在華召開","version":1504073115,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/b46177be-afcf-4aa3-8f89-46a4f3f051b3.jpg"},{"id":2228456,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228456.json?v=1504073115","title":"塞罕壩:踐行\u201c兩山\u201d理論發展生態旅遊","version":1504073115,"pic1":""}]},{"id":225824,"name":"旅遊報04版","date":"2017-08-30","picUrl":"https://img.newaircloud.com/xkycs/paper/201708/30/a5e3736e-d71b-4782-864c-0fc21b48c179.jpg","height":2009,"width":1259,"mapping":[{"mapping":["67.649879%,69.255663%","67.649879%,72.815534%","98.118145%,72.815534%","98.118145%,69.255663%","67.649879%,69.255663%","76.945282%,67.637540%","76.945282%,68.608414%","89.080947%,68.608414%","89.080947%,67.637540%","76.945282%,67.637540%"],"articleID":"2228458"},{"mapping":["67.649879%,62.459547%","67.649879%,66.666667%","98.118145%,66.666667%","98.118145%,62.459547%","67.649879%,62.459547%","78.494516%,60.679612%","78.494516%,61.650485%","89.080947%,61.650485%","89.080947%,60.679612%","78.494516%,60.679612%"],"articleID":"2228459"},{"mapping":["67.649879%,55.501618%","67.649879%,59.708738%","98.118145%,59.708738%","98.118145%,55.501618%","67.649879%,55.501618%","75.137842%,53.721683%","75.137842%,54.530744%","90.888387%,54.530744%","90.888387%,53.721683%","75.137842%,53.721683%"],"articleID":"2228460"},{"mapping":["67.649879%,43.042071%","98.118145%,43.042071%","98.118145%,9.385113%","67.649879%,9.385113%"],"articleID":"2228461"},{"mapping":["64.809617%,72.815534%","1.807440%,72.815534%","1.807440%,46.601942%","1.807440%,36.245955%","1.807440%,9.546926%","64.809617%,9.546926%","64.809617%,13.106796%","64.809617%,24.110032%"],"articleID":"2228462"}],"list":[{"id":2228458,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228458.json?v=1504073120","title":"智利:Puyuhuapi","version":1504073120,"pic1":""},{"id":2228459,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228459.json?v=1504073120","title":"土耳其:布爾薩","version":1504073120,"pic1":""},{"id":2228460,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228460.json?v=1504073120","title":"哥斯達黎加:阿雷納爾","version":1504073120,"pic1":""},{"id":2228462,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228462.json?v=1504073131","title":"港企珠海御溫泉:20年專注一件事","version":1504073131,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/c886ae48-4c76-4969-96d9-eb13733cd068.jpg"}]},{"id":225825,"name":"旅遊報05版","date":"2017-08-30","picUrl":"https://img.newaircloud.com/xkycs/paper/201708/30/43532b57-0c1c-4a8c-9404-6b5f150ee069.jpg","height":2009,"width":1259,"mapping":[{"mapping":["26.595181%,92.394822%","97.859939%,92.394822%","97.859939%,44.822006%","26.595181%,44.822006%"],"articleID":"2228463"},{"mapping":["3.873085%,92.394822%","22.205685%,92.394822%","22.205685%,47.087379%","3.873085%,47.087379%"],"articleID":"2228464"}],"list":[{"id":2228463,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228463.json?v=1504073142","title":"曬鹽的女人","version":1504073142,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/1ddf6da0-f25b-4233-9350-4ac9f16225a6.jpg"},{"id":2228464,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228464.json?v=1504073144","title":"茶馬驛鎮","version":1504073144,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/9fb35060-5819-465d-85ec-525804fd6936.jpg"}]},{"id":225826,"name":"旅遊報06版","date":"2017-08-30","picUrl":"https://img.newaircloud.com/xkycs/paper/201708/30/3bcadbec-e108-4b7d-84c8-31873b9349c7.jpg","height":2009,"width":1259,"mapping":[{"mapping":["2.065645%,94.336570%","97.859939%,94.336570%","97.859939%,52.750809%","2.065645%,52.750809%"],"articleID":"2228466"},{"mapping":["97.859939%,49.838188%","2.065645%,49.838188%","2.065645%,26.537217%","2.065645%,16.666667%","2.065645%,5.663430%","97.859939%,5.663430%"],"articleID":"2228467"}],"list":[{"id":2228466,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228466.json?v=1504073159","title":"高原至味","version":1504073159,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/3bb5c7b8-e1c9-4045-9da7-3a2abae05746.jpg"},{"id":2228467,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228467.json?v=1504073167","title":"湖畔香巴拉","version":1504073167,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/613f42c9-49e1-4731-aae1-b92ad55a5a51.jpg"}]},{"id":225827,"name":"旅遊報07版","date":"2017-08-30","picUrl":"https://img.newaircloud.com/xkycs/paper/201708/30/5bde9f8d-37a4-4a9a-b7cb-8ed880707dff.jpg","height":2009,"width":1259,"mapping":[{"mapping":["2.323851%,94.336570%","97.859939%,94.336570%","97.859939%,50.970874%","2.323851%,50.970874%"],"articleID":"2228469"},{"mapping":["2.065645%,48.058252%","97.859939%,48.058252%","97.859939%,5.663430%","2.065645%,5.663430%"],"articleID":"2228470"}],"list":[{"id":2228469,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228469.json?v=1504073178","title":"\u201c百裏挑一\u201d之城","version":1504073178,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/6e510dec-fd75-4728-b2bf-ae2d97a46cfe.jpg"},{"id":2228470,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228470.json?v=1504073185","title":"酥油茶和藏香雞","version":1504073185,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/4bf8b082-16da-494c-8d3d-c6596fd5bbd0.jpg"}]},{"id":225828,"name":"旅遊報08版","date":"2017-08-30","picUrl":"https://img.newaircloud.com/xkycs/paper/201708/30/2b483913-0c4e-443f-a90e-00c86220db64.jpg","height":2009,"width":1259,"mapping":[{"mapping":["75.654254%,87.702265%","95.536088%,87.702265%","95.536088%,6.634304%","75.654254%,6.634304%"],"articleID":"2228471"},{"mapping":["71.264758%,94.336570%","2.065645%,94.336570%","2.065645%,6.634304%","71.264758%,6.634304%","71.264758%,64.563107%","71.264758%,73.139159%","71.264758%,73.786408%","71.264758%,81.877023%"],"articleID":"2228472"}],"list":[{"id":2228471,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228471.json?v=1504073192","title":"無關風月","version":1504073192,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/a55bd6a1-e833-4422-bdaf-70f3d1ea77d0.jpg"},{"id":2228472,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228472.json?v=1504073208","title":"張榮強:將版刻年畫進行到底","version":1504073208,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/c5e962d6-8f5c-4dd2-8ccf-3eea14aefb78.jpg"}]},{"id":225829,"name":"旅遊報09版","date":"2017-08-30","picUrl":"https://img.newaircloud.com/xkycs/paper/201708/30/d9400602-220e-4093-96ab-0dfa812c5a53.jpg","height":2009,"width":1259,"mapping":[{"mapping":["98.118145%,95.954693%","1.807440%,95.954693%","1.807440%,95.792880%","1.807440%,61.650485%","1.807440%,48.705502%","1.807440%,42.233010%","1.807440%,4.854369%","98.118145%,4.854369%","98.118145%,67.637540%","98.118145%,95.792880%"],"articleID":"2228473"}],"list":[{"id":2228473,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228473.json?v=1504073215","title":"旅遊業持續井噴,發展紅利惠","version":1504073215,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/54e2ee51-17fd-4949-bb61-5777a83613eb.jpg"}]},{"id":225830,"name":"旅遊報10版","date":"2017-08-30","picUrl":"https://img.newaircloud.com/xkycs/paper/201708/30/5839325f-83c8-4380-aedf-cffaaa459ada.jpg","height":2009,"width":1259,"mapping":[{"mapping":["1.807440%,95.954693%","54.739597%,95.954693%","54.739597%,39.644013%","1.807440%,39.644013%"],"articleID":"2228474"},{"mapping":["59.387298%,95.954693%","98.376350%,95.954693%","98.376350%,36.731392%","59.387298%,36.731392%"],"articleID":"2228475"},{"mapping":["1.807440%,37.216828%","98.118145%,37.216828%","98.118145%,4.854369%","1.807440%,4.854369%"],"articleID":"2228476"}],"list":[{"id":2228474,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228474.json?v=1504073229","title":"一個漁港一片海","version":1504073229,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/462ee057-7d91-4196-8c4e-6a448a9e22ce.jpg"},{"id":2228475,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228475.json?v=1504073236","title":"石塘\u2014\u2014","version":1504073236,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/d79493ed-5664-4568-b6ad-ff3c5a6bf301.jpg"},{"id":2228476,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228476.json?v=1504073241","title":"一個漁港一片海一縷陽光一座城","version":1504073241,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/ae3a8f37-37f5-4de6-9291-cbcd2170718f.jpg"}]},{"id":225831,"name":"旅遊報11版","date":"2017-08-30","picUrl":"https://img.newaircloud.com/xkycs/paper/201708/30/ada8cc40-e084-45db-9586-b813b6e887e9.jpg","height":2009,"width":1259,"mapping":[{"mapping":["75.912459%,83.818770%","55.772419%,83.818770%","55.772419%,49.190939%","55.772419%,48.381877%","55.772419%,47.087379%","75.912459%,47.087379%"],"articleID":"2228477"},{"mapping":["98.118145%,81.553398%","81.334778%,81.553398%","81.334778%,39.482201%","81.334778%,38.673139%","81.334778%,37.378641%","98.118145%,37.378641%"],"articleID":"2228478"},{"mapping":["31.501089%,77.831715%","50.608306%,77.831715%","50.608306%,36.893204%","31.501089%,36.893204%"],"articleID":"2228479"},{"mapping":["7.229758%,67.313916%","27.369798%,67.313916%","27.369798%,38.025890%","7.229758%,38.025890%"],"articleID":"2228480"},{"mapping":["1.807440%,35.113269%","98.118145%,35.113269%","98.118145%,4.854369%","1.807440%,4.854369%"],"articleID":"2228481"}],"list":[{"id":2228479,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228479.json?v=1504073246","title":"杭州旅遊全域化成效初顯","version":1504073246,"pic1":""},{"id":2228480,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228480.json?v=1504073246","title":"杭州旅遊精準發力","version":1504073246,"pic1":""},{"id":2228481,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228481.json?v=1504073246","title":"向國際重要的旅遊休閒中心奮力邁進","version":1504073246,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/6fc97c07-7904-41b0-b208-97f93cb7bff8.jpg"}]},{"id":225832,"name":"旅遊報12版","date":"2017-08-30","picUrl":"https://img.newaircloud.com/xkycs/paper/201708/30/9f0c9442-b20f-43d5-b000-88a3eaa6264c.jpg","height":2009,"width":1259,"mapping":[{"mapping":["2.323851%,94.498382%","97.601734%,94.498382%","97.601734%,81.715210%","2.323851%,81.715210%"],"articleID":"2228482"},{"mapping":["69.457318%,78.802589%","96.827117%,78.802589%","96.827117%,69.579288%","69.457318%,69.579288%"],"articleID":"2228483"},{"mapping":["66.100645%,79.288026%","19.365423%,79.288026%","19.365423%,72.168285%","19.365423%,65.048544%","19.365423%,63.592233%","66.100645%,63.592233%","66.100645%,65.533981%"],"articleID":"2228484"},{"mapping":["69.457318%,68.608414%","96.827117%,68.608414%","96.827117%,58.737864%","69.457318%,58.737864%"],"articleID":"2228485"},{"mapping":["19.623629%,61.974110%","65.842439%,61.974110%","65.842439%,51.456311%","19.623629%,51.456311%"],"articleID":"2228486"},{"mapping":["69.457318%,57.605178%","96.827117%,57.605178%","96.827117%,46.278317%","69.457318%,46.278317%"],"articleID":"2228487"},{"mapping":["69.199113%,44.983819%","96.827117%,44.983819%","96.827117%,34.304207%","69.199113%,34.304207%"],"articleID":"2228488"},{"mapping":["3.356673%,78.802589%","15.750544%,78.802589%","15.750544%,28.155340%","3.356673%,28.155340%"],"articleID":"2228489"},{"mapping":["19.365423%,49.514563%","66.100645%,49.514563%","66.100645%,27.508091%","19.365423%,27.508091%"],"articleID":"2228490"},{"mapping":["69.457318%,33.333333%","96.827117%,33.333333%","96.827117%,21.035599%","69.457318%,21.035599%"],"articleID":"2228491"},{"mapping":["69.457318%,19.579288%","96.827117%,19.579288%","96.827117%,8.252427%","69.457318%,8.252427%"],"articleID":"2228492"},{"mapping":["2.323851%,25.728155%","65.842439%,25.728155%","65.842439%,5.987055%","2.323851%,5.987055%"],"articleID":"2228493"}],"list":[{"id":2228482,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228482.json?v=1504073251","title":"中國肥城第十屆金秋品桃節啓動","version":1504073251,"pic1":""},{"id":2228483,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228483.json?v=1504073251","title":"首屆復聖茶器文化展精品雲集","version":1504073251,"pic1":""},{"id":2228484,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228484.json?v=1504073252","title":"騎着摩拜去膜拜時尚情懷融入傳統文化","version":1504073252,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/9c88220a-7e98-40c0-9f51-06d275825851.jpg"},{"id":2228485,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228485.json?v=1504073252","title":"齊河將建溫泉度假小鎮","version":1504073252,"pic1":""},{"id":2228486,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228486.json?v=1504073252","title":"棗莊薛城:紅色文化帶動全域旅遊發展","version":1504073252,"pic1":""},{"id":2228487,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228487.json?v=1504073252","title":"青島城陽多措並舉激發旅遊新動能","version":1504073252,"pic1":""},{"id":2228488,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228488.json?v=1504073252","title":"東營·利津綦家嘴迎來《我是大明星》","version":1504073252,"pic1":""},{"id":2228489,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228489.json?v=1504073252","title":"短訊","version":1504073252,"pic1":""},{"id":2228490,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228490.json?v=1504073254","title":"第四屆香草文化旅遊節活動豐富","version":1504073254,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/da11bcb4-622e-4020-891c-ad0eae01dcf9.jpg"},{"id":2228491,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228491.json?v=1504073254","title":"珠光寶氣\u201c閃耀\u201d泰安","version":1504073254,"pic1":""},{"id":2228492,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228492.json?v=1504073255","title":"2017黃河口公路自行車賽下月舉辦","version":1504073255,"pic1":""},{"id":2228493,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228493.json?v=1504073257","title":"\u201c山東好禮\u201d出新品","version":1504073257,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/b1ea017c-7596-4e83-9dc8-a40bc0bfd825.jpg"}]}]
     * date : 2017-08-30
     */

    private int version;
    private String date;
    private List<LayoutsBean> layouts;

    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public List<LayoutsBean> getLayouts() {
        return layouts;
    }

    public void setLayouts(List<LayoutsBean> layouts) {
        this.layouts = layouts;
    }

    public static class LayoutsBean {
        /**
         * id : 225823
         * name : 旅遊報01版
         * date : 2017-08-30
         * picUrl : https://img.newaircloud.com/xkycs/paper/201708/30/d9f405e7-2a7e-4459-a6e9-324e41f31927.jpg
         * height : 2009
         * width : 1259
         * mapping : [{"mapping":["66.617056%,82.362460%","98.118145%,82.362460%","98.118145%,66.181230%","66.617056%,66.181230%"],"articleID":"2228451"},{"mapping":["1.807440%,79.288026%","63.776794%,79.288026%","63.776794%,58.899676%","1.807440%,58.899676%"],"articleID":"2228452"},{"mapping":["67.649879%,63.430421%","97.085322%,63.430421%","97.085322%,49.029126%","67.649879%,49.029126%"],"articleID":"2228453"},{"mapping":["97.085322%,47.087379%","67.649879%,47.087379%","67.649879%,36.245955%","67.649879%,35.436893%","67.649879%,35.436893%","67.649879%,28.640777%","74.621431%,28.640777%","75.137842%,27.993528%","75.137842%,22.977346%","89.597359%,22.977346%","89.597359%,27.993528%","97.085322%,28.802589%"],"articleID":"2228454"},{"mapping":["1.807440%,54.045307%","64.035000%,54.045307%","64.035000%,17.961165%","1.807440%,17.961165%"],"articleID":"2228455"},{"mapping":["58.096270%,15.210356%","98.118145%,15.210356%","98.118145%,2.103560%","58.096270%,2.103560%"],"articleID":"2228456"}]
         * list : [{"id":2228451,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228451.json?v=1504073111","title":"醫療旅遊服務產業成重要方向","version":1504073111,"pic1":""},{"id":2228452,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228452.json?v=1504073111","title":"內蒙古以全域旅遊之筆繪行業發展藍圖","version":1504073111,"pic1":""},{"id":2228453,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228453.json?v=1504073112","title":"城市旅遊","version":1504073112,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/baa4058e-d021-4e6a-b515-d1631976a5b1.jpg"},{"id":2228454,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228454.json?v=1504073113","title":"大詞彙文化旅遊","version":1504073113,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/715b3468-93ef-4e60-8730-ec00a2002de0.jpg"},{"id":2228455,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228455.json?v=1504073115","title":"澳大利亞全國旅遊會議首次在華召開","version":1504073115,"pic1":"https://img.newaircloud.com/xkycs/paper/201708/30/b46177be-afcf-4aa3-8f89-46a4f3f051b3.jpg"},{"id":2228456,"curl":"https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228456.json?v=1504073115","title":"塞罕壩:踐行\u201c兩山\u201d理論發展生態旅遊","version":1504073115,"pic1":""}]
         */

        private int id;
        private String name;
        private String date;
        private String picUrl;
        private int height;
        private int width;
        private List<MappingBean> mapping;
        private List<ListBean> list;

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getDate() {
            return date;
        }

        public void setDate(String date) {
            this.date = date;
        }

        public String getPicUrl() {
            return picUrl;
        }

        public void setPicUrl(String picUrl) {
            this.picUrl = picUrl;
        }

        public int getHeight() {
            return height;
        }

        public void setHeight(int height) {
            this.height = height;
        }

        public int getWidth() {
            return width;
        }

        public void setWidth(int width) {
            this.width = width;
        }

        public List<MappingBean> getMapping() {
            return mapping;
        }

        public void setMapping(List<MappingBean> mapping) {
            this.mapping = mapping;
        }

        public List<ListBean> getList() {
            return list;
        }

        public void setList(List<ListBean> list) {
            this.list = list;
        }

        public static class MappingBean {
            /**
             * mapping : ["66.617056%,82.362460%","98.118145%,82.362460%","98.118145%,66.181230%","66.617056%,66.181230%"]
             * articleID : 2228451
             */

            private String articleID;
            private List<String> mapping;

            public String getArticleID() {
                return articleID;
            }

            public void setArticleID(String articleID) {
                this.articleID = articleID;
            }

            public List<String> getMapping() {
                return mapping;
            }

            public void setMapping(List<String> mapping) {
                this.mapping = mapping;
            }
        }

        public static class ListBean {
            /**
             * id : 2228451
             * curl : https://oss.newaircloud.com/xkycs/paper/article/201708/30/c2228451.json?v=1504073111
             * title : 醫療旅遊服務產業成重要方向
             * version : 1504073111
             * pic1 :
             */

            private int id;
            private String curl;
            private String title;
            private int version;
            private String pic1;

            public int getId() {
                return id;
            }

            public void setId(int id) {
                this.id = id;
            }

            public String getCurl() {
                return curl;
            }

            public void setCurl(String curl) {
                this.curl = curl;
            }

            public String getTitle() {
                return title;
            }

            public void setTitle(String title) {
                this.title = title;
            }

            public int getVersion() {
                return version;
            }

            public void setVersion(int version) {
                this.version = version;
            }

            public String getPic1() {
                return pic1;
            }

            public void setPic1(String pic1) {
                this.pic1 = pic1;
            }
        }
    }
}

model包
創建IModel接口
package com.example.dasd.yuekao1.model;

/**
 * Created by yujie on 2018/1/18.
 */

public interface IModel {
    void onModelSuccess(DataDataBean dataDataBean);
    void onModelError();
}

model包
Model.java
package com.example.dasd.yuekao1.model;

import com.example.dasd.yuekao1.util.RetrofitHelper;
import com.google.gson.Gson;

import java.util.Map;

import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
 * Created by yujie on 2018/1/18.
 */

public class Model {
    private IModel iModel;

    public Model(IModel iModel) {
        this.iModel = iModel;
    }

    public void getData(String baseUrl, String url, Map<String, String> params){
        RetrofitHelper.getApiService(baseUrl)
                .getData(url, params)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        iModel.onModelError();
                    }

                    @Override
                    public void onNext(String s) {
                        Gson gson = new Gson();
                        DataDataBean dataDataBean = gson.fromJson(s, DataDataBean.class);
                        iModel.onModelSuccess(dataDataBean);
                    }
                });
    }
}

presentere包
實現IPresenter接口
package com.example.dasd.yuekao1.presenter;


import com.example.dasd.yuekao1.model.DataDataBean;

/**
 * Created by yujie on 2018/1/18.
 */

public interface IPresenter {
    void onPreSuccess(DataDataBean dataDataBean);
    void onPreError();
}


presentere包
PresenterImpl.java
package com.example.dasd.yuekao1.presenter;


import com.example.dasd.yuekao1.base.BasePresenter;
import com.example.dasd.yuekao1.model.DataDataBean;
import com.example.dasd.yuekao1.model.IModel;
import com.example.dasd.yuekao1.model.Model;

import java.util.Map;

/**
 * Created by yujie on 2018/1/18.
 */

public class PresenterImpl extends BasePresenter<IPresenter> implements IModel {
    private Model model;

    @Override
    protected void initModel() {
        model = new Model(this);
    }

    public void getData(String baseUrl, String url, Map<String, String> params){
        model.getData(baseUrl, url, params);
    }

    @Override
    public void onModelSuccess(DataDataBean dataDataBean) {
        iPresenter.onPreSuccess(dataDataBean);
    }

    @Override
    public void onModelError() {
        iPresenter.onPreError();
    }
}


util包
Api.java
package com.example.dasd.yuekao1.util;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by yujie on 2018/1/18.
 */

public class Api {
    //http://h5test.newaircloud.com/api/getLayouts?sid=xkycs&cid=10024&date=
    public static final String BASE_URL = "http://h5test.newaircloud.com/api/";
    public static final String URL = "getLayouts";
    public static Map<String, String> getParams(){
        Map<String, String> params = new HashMap<>();
        params.put("sid", "xkycs");
        params.put("cid", "10024");
        return params;
    }
}

util包
ApiService接口
package com.example.dasd.yuekao1.util;

import java.util.Map;

import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.QueryMap;
import retrofit2.http.Url;
import rx.Observable;

/**
 * Created by yujie on 2018/1/18.
 */

public interface ApiService {
    @GET
    Observable<String> getData(@Url String url);

    @GET
    Observable<String> getData(@Url String url, @QueryMap Map<String, String> params);

    @FormUrlEncoded
    @POST
    Observable<String> postData(@Url String url);

    @FormUrlEncoded
    @POST
    Observable<String> postData(@Url String url, @FieldMap Map<String, String> params);
}


util包
CrashHandler.java
package com.example.dasd.yuekao1.util;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.os.Looper;
import android.os.Process;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * Created by Dash on 2017/12/7.
 */
public class CrashHandler implements Thread.UncaughtExceptionHandler {
    private static CrashHandler crashHandler;
    private Context context;
    private Thread.UncaughtExceptionHandler defaultHandler;
    //存日誌文件的目錄(文件夾)
    private File logDir = new File(Environment.getExternalStorageDirectory(),"error");
    //時間格式化
    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS", Locale.CHINA);

    /**
     * 對外提供獲取實例對象的方法....單例模式
     * @return
     */
    public static CrashHandler getInstace(){
        if (crashHandler == null){
            synchronized (CrashHandler.class){
                if (crashHandler == null){
                    crashHandler = new CrashHandler();
                }
            }
        }

        return crashHandler;
    }

    /**
     * 初始化的時候.....
     * @param context
     */
    public void init(Context context){
        this.context = context;

        //先拿到系統默認的異常處理器
        defaultHandler = Thread.getDefaultUncaughtExceptionHandler();

        //設置當前作爲我們處理異常的處理器
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     * 當異常發生的時候會自動調用uncaughtException方法
     * @param thread
     * @param throwable
     */
    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        //自己沒有處理異常,交給系統來處理
        if (!handlerException(throwable) && defaultHandler != null){
            defaultHandler.uncaughtException(thread,throwable);
        }else {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //否則自己處理了異常....上傳服務器
            uploadLogToServer();
            //結束進程 退出程序
            Process.killProcess(Process.myPid());//殺死應用的進程
            //非正常退出應用....0表示正常退出,,,非0表示不正常
            System.exit(10);
        }
    }

    /**
     * 上傳文件到服務器
     */
    private void uploadLogToServer() {
        //遍歷sd卡中crash文件夾,,,得到每一個文件

        //使用okhttp的post方式上傳file文件

        //把上傳的文件crash文件夾中刪除

    }

    /**
     * 自己處理異常的方法
     * @return
     * @param throwable
     */
    private boolean handlerException(Throwable throwable) {
        if (throwable == null){
            return false;
        }
        //吐司提示一下
        new Thread(){
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(context,"程序異常",Toast.LENGTH_SHORT).show();
                Looper.loop();
            }
        }.start();

        //日誌寫到文件中去
        if (! logDir.exists()){
            logDir.mkdirs();
        }

        //文件夾中創建文件...crash-2017-12-07-HH-mm-ss-SSS.log
        File logFile = new File(logDir,"crash-"+dateFormat.format(new Date())+"-.log");
        if (!logFile.exists()){
            try {
                logFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        //寫入sd卡...使用打印流
        try {
            PrintWriter printWriter = new PrintWriter(logFile);

            collectLogInfoToSdCard(printWriter,throwable);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }


        return true;
    }

    /**
     * 寫入sd卡
     * @param printWriter
     * @param throwable
     */
    private void collectLogInfoToSdCard(PrintWriter printWriter, Throwable throwable) {
        //日誌裏面可能會喲版本號 版本名稱 時間

        //獲取pakage管理者對象
        PackageManager packageManager = context.getPackageManager();
        //獲取當前應用的信息....(context.getPackageName()獲取當前應用的包名
        try {
            PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);

            printWriter.print("版本:");
            printWriter.println(packageInfo.versionCode);
            printWriter.print("版本名稱:");
            printWriter.println(packageInfo.versionName);

            printWriter.print("time");
            printWriter.println(dateFormat.format(new Date()));

            //把日誌信息放到打印流中去打印
            throwable.printStackTrace(printWriter);

            printWriter.close();

        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

    }
}

util包
ImagePipelineConfigUtils.java
package com.example.dasd.yuekao1.util;

import android.content.Context;
import android.graphics.Bitmap;
import android.os.Environment;
import android.util.Log;

import com.facebook.cache.disk.DiskCacheConfig;
import com.facebook.common.disk.NoOpDiskTrimmableRegistry;
import com.facebook.common.internal.Supplier;
import com.facebook.common.memory.MemoryTrimType;
import com.facebook.common.memory.MemoryTrimmable;
import com.facebook.common.memory.NoOpMemoryTrimmableRegistry;
import com.facebook.common.util.ByteConstants;
import com.facebook.imagepipeline.cache.MemoryCacheParams;
import com.facebook.imagepipeline.core.ImagePipelineConfig;
import com.facebook.imagepipeline.core.ImagePipelineFactory;

/**
 * Created by yujie on 2018/1/18.
 */

public class ImagePipelineConfigUtils {
    //分配的可用內存
    private static final int MAX_HEAP_SIZE = (int) Runtime.getRuntime().maxMemory();
    //使用的緩存數量
    private static final int MAX_MEMORY_CACHE_SIZE = MAX_HEAP_SIZE / 4;
    //小圖極低磁盤空間緩存的最大值(特性:可將大量的小圖放到額外放在另一個磁盤空間防止大圖佔用磁盤空間而刪除了大量的小圖)
    private static final int MAX_SMALL_DISK_VERYLOW_CACHE_SIZE = 20 * ByteConstants.MB;
    //小圖低磁盤空間緩存的最大值(特性:可將大量的小圖放到額外放在另一個磁盤空間防止大圖佔用磁盤空間而刪除了大量的小圖)
    private static final int MAX_SMALL_DISK_LOW_CACHE_SIZE = 60 * ByteConstants.MB;
    //默認圖極低磁盤空間緩存的最大值
    private static final int MAX_DISK_CACHE_VERYLOW_SIZE = 20 * ByteConstants.MB;
    //默認圖低磁盤空間緩存的最大值
    private static final int MAX_DISK_CACHE_LOW_SIZE = 60 * ByteConstants.MB;
    //默認圖磁盤緩存的最大值
    private static final int MAX_DISK_CACHE_SIZE = 100 * ByteConstants.MB;
    //小圖所放路徑的文件夾名
    private static final String IMAGE_PIPELINE_SMALL_CACHE_DIR = "ImagePipelineCacheSmall";
    //默認圖所放路徑的文件夾名
    private static final String IMAGE_PIPELINE_CACHE_DIR = "ImagePipelineCacheDefault";
    public static ImagePipelineConfig getDefaultImagePipelineConfig(Context context) {
        //內存配置
        final MemoryCacheParams bitmapCacheParams = new MemoryCacheParams(
                MAX_MEMORY_CACHE_SIZE,// 內存緩存中總圖片的最大大小,以字節爲單位。
                Integer.MAX_VALUE,// 內存緩存中圖片的最大數量。
                MAX_MEMORY_CACHE_SIZE,// 內存緩存中準備清除但尚未被刪除的總圖片的最大大小,以字節爲單位。
                Integer.MAX_VALUE,// 內存緩存中準備清除的總圖片的最大數量。
                Integer.MAX_VALUE);// 內存緩存中單個圖片的最大大小。
        //修改內存圖片緩存數量,空間策略(這個方式有點噁心)
        Supplier<MemoryCacheParams> mSupplierMemoryCacheParams = new Supplier<MemoryCacheParams>() {
            @Override
            public MemoryCacheParams get() {
                return bitmapCacheParams;
            }
        };
        //小圖片的磁盤配置
        DiskCacheConfig diskSmallCacheConfig = DiskCacheConfig.newBuilder(context).setBaseDirectoryPath(context.getApplicationContext().getCacheDir())//緩存圖片基路徑
                .setBaseDirectoryName(IMAGE_PIPELINE_SMALL_CACHE_DIR)//文件夾名
                .setMaxCacheSize(MAX_DISK_CACHE_SIZE)//默認緩存的最大大小。
                .setMaxCacheSizeOnLowDiskSpace(MAX_SMALL_DISK_LOW_CACHE_SIZE)//緩存的最大大小,使用設備時低磁盤空間。
                .setMaxCacheSizeOnVeryLowDiskSpace(MAX_SMALL_DISK_VERYLOW_CACHE_SIZE)//緩存的最大大小,當設備極低磁盤空間
                .setDiskTrimmableRegistry(NoOpDiskTrimmableRegistry.getInstance())
                .build();
        //默認圖片的磁盤配置
        DiskCacheConfig diskCacheConfig = DiskCacheConfig.newBuilder(context).setBaseDirectoryPath(Environment.getExternalStorageDirectory().getAbsoluteFile())//緩存圖片基路徑
                .setBaseDirectoryName(IMAGE_PIPELINE_CACHE_DIR)//文件夾名
                .setMaxCacheSize(MAX_DISK_CACHE_SIZE)//默認緩存的最大大小。
                .setMaxCacheSizeOnLowDiskSpace(MAX_DISK_CACHE_LOW_SIZE)//緩存的最大大小,使用設備時低磁盤空間。
                .setMaxCacheSizeOnVeryLowDiskSpace(MAX_DISK_CACHE_VERYLOW_SIZE)//緩存的最大大小,當設備極低磁盤空間
                .setDiskTrimmableRegistry(NoOpDiskTrimmableRegistry.getInstance())
                .build();
        //緩存圖片配置
        ImagePipelineConfig.Builder configBuilder = ImagePipelineConfig.newBuilder(context)
                .setBitmapsConfig(Bitmap.Config.RGB_565)
                .setBitmapMemoryCacheParamsSupplier(mSupplierMemoryCacheParams)
                .setSmallImageDiskCacheConfig(diskSmallCacheConfig)
                .setMainDiskCacheConfig(diskCacheConfig)
                .setMemoryTrimmableRegistry(NoOpMemoryTrimmableRegistry.getInstance())
                .setResizeAndRotateEnabledForNetwork(true);
        // 就是這段代碼,用於清理緩存
        NoOpMemoryTrimmableRegistry.getInstance().registerMemoryTrimmable(new MemoryTrimmable() {
            @Override
            public void trim(MemoryTrimType trimType) {
                final double suggestedTrimRatio = trimType.getSuggestedTrimRatio();
                Log.d("", String.format("onCreate suggestedTrimRatio : %d", suggestedTrimRatio));
                if (MemoryTrimType.OnCloseToDalvikHeapLimit.getSuggestedTrimRatio() == suggestedTrimRatio
                        || MemoryTrimType.OnSystemLowMemoryWhileAppInBackground.getSuggestedTrimRatio() == suggestedTrimRatio
                        || MemoryTrimType.OnSystemLowMemoryWhileAppInForeground.getSuggestedTrimRatio() == suggestedTrimRatio
                        ) {
                    ImagePipelineFactory.getInstance().getImagePipeline().clearMemoryCaches();
                }
            }
        });
        return configBuilder.build();
    }
}


util包
RetrofitHelper.java
package com.example.dasd.yuekao1.util;

import android.os.Environment;

import java.io.File;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;

/**
 * Created by yujie on 2018/1/18.
 */

public class RetrofitHelper {
    public static OkHttpClient okHttpClient;
    public static ApiService apiService;

    static {
        getOkHttpClient();
    }

    public static OkHttpClient getOkHttpClient(){
        if(okHttpClient == null){
            synchronized (OkHttpClient.class) {
                if(okHttpClient == null){
                    File fileDir = new File(Environment.getExternalStorageDirectory(), "cache");
                    long fileSize = 10 * 1024 * 1024;
                    okHttpClient = new OkHttpClient.Builder()
                            .connectTimeout(15, TimeUnit.SECONDS)
                            .readTimeout(15, TimeUnit.SECONDS)
                            .writeTimeout(15, TimeUnit.SECONDS)
                            .cache(new Cache(fileDir, fileSize))
                            .build();
                }
            }
        }
        return okHttpClient;
    }

    public static ApiService getApiService(String baseUrl){
        if(apiService == null){
            synchronized (OkHttpClient.class) {
                apiService = createApiService(baseUrl, ApiService.class);
            }
        }
        return apiService;
    }

    private static <T>T createApiService(String baseUrl, Class<T> tClass) {
        T t = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(okHttpClient)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build()
                .create(tClass);
        return t;
    }

}








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章