Rxjava+retrofit+okHttp+mvp网络请求数据

//Api类

public class Api {
    //http://api.svipmovie.com/front/columns/getVideoList.do?catalogId=402834815584e463015584e539330016
    public static final String benUrl="http://api.svipmovie.com/front/columns/";

}

//Api接口

public interface ApiSevert {
//      getVideoList.do?catalogId=402834815584e463015584e539330016
        @GET("getVideoList.do?catalogId=402834815584e463015584e539330016")
        Observable<Bean> getNoPrea();

}

//model层

public interface MainActivityModelListener {
      void getData(OnFinish finish);
}
public class MainActivityModel implements MainActivityModelListener {

    @Override
    public void getData(final OnFinish finish) {
        OkHttpClient okHttpClient=new OkHttpClient.Builder()
                //网络拦截器
               // .addInterceptor(new LoggingInterceptor())
                .build();

        Retrofit retrofit=new Retrofit.Builder()
                .baseUrl(Api.benUrl)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                //
                .client(okHttpClient)
                .build();
        Observable<Bean> getNoPrea = retrofit.create(ApiSevert.class).getNoPrea();
        getNoPrea.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Bean>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(Bean bean) {

                        finish.finish(bean);
                    }
                });
    }
}

//view层

public interface MainActivityViewListener {
        void ShowData(Bean bean);
}

//presenter层,Bean层自己实现

public interface IPresenter {
    void loadList();
}
public class ListPresenter implements IPresenter {
    private final MainActivityModelListener molder;
    private MainActivityViewListener gv;
    public ListPresenter(MainActivityViewListener gv) {
        this.gv=gv;
        molder=new MainActivityModel();
    }


    @Override
    public void loadList() {
          molder.getData(new OnFinish() {
              @Override
              public void finish(Bean bean) {
                  gv.ShowData(bean);
              }
          });
    }
}

//适配器

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>  implements View.OnClickListener,View.OnLongClickListener{

    //点击事件
    private OnItemClickListener mOnItemClickListener = null;
    //长按点击事件
    private OnRecyclerItemLongListener mOnItemLong = null;
    private Context context;
    private List<Bean.RetBean.ListBean>list;

    public MyAdapter(Context context,List<Bean.RetBean.ListBean> list) {
        this.context = context;
        this.list = list;
    }


    public void setData(Bean bean) {

        if (this.list == null) {
            this.list = new ArrayList<>();
        }
        this.list.addAll(bean.getRet().getList());
        notifyDataSetChanged();

    }


    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.item, parent, false);
        ViewHolder holder=new ViewHolder(view);
        view.setOnClickListener(this);
        view.setOnLongClickListener(this);
        return holder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        ViewGroup.LayoutParams params = holder.img.getLayoutParams();//得到item的LayoutParams布局参数
        holder.img.setLayoutParams(params);//把params设置给itemView布局
        Uri uri = Uri.parse(list.get(position).getPic());
        holder.img.setImageURI(uri);
        holder.tv.setText(list.get(position).getTitle());
        holder.tv2.setText(list.get(position).getDuration());
            holder.itemView.setTag(position);

    }

    @Override
    public int getItemCount() {
        return list == null ? 0 : list.size();
    }



    //长按点击事件
    public interface OnRecyclerItemLongListener{
        void onItemLongClick(View view,int position);
    }
    public void setOnItemLongClickListener(OnRecyclerItemLongListener listener){
        this.mOnItemLong =  listener;
    }
    @Override
    public boolean onLongClick(View view) {
        if(mOnItemLong != null){
            mOnItemLong.onItemLongClick(view,1);
        }
        return true;
    }


    //点击事件接口
    //define interface
    public static interface OnItemClickListener {
        void onItemClick(View view , int position);
    }
    public void setOnItemClickListener(OnItemClickListener listener) {
        this.mOnItemClickListener = listener;
    }
    @Override
    public void onClick(View view) {
        if (mOnItemClickListener != null) {
            //注意这里使用getTag方法获取position
            mOnItemClickListener.onItemClick(view,(int)view.getTag());
        }
    }



    public class ViewHolder extends RecyclerView.ViewHolder{
        public SimpleDraweeView img;
        public TextView tv,tv2;
        public ViewHolder(View itemView) {
            super(itemView);
            img=itemView.findViewById(R.id.img);
            tv=itemView.findViewById(R.id.tv1);
            tv2=itemView.findViewById(R.id.tv2);
        }
    }
}

//适配器布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"

    android:orientation="vertical"
    android:layout_height="wrap_content">
    <com.facebook.drawee.view.SimpleDraweeView
        android:scaleType="fitXY"
        android:padding="10dp"
        android:id="@+id/img"
        android:src="@mipmap/ic_launcher_round"
        android:layout_width="120dp"
        android:layout_height="120dp"
        fresco:viewAspectRatio="1.33"/>
    <!--<!– other attributes –>-->


    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/tv1"
            android:padding="10dp"
            android:text="成都"
            android:textSize="20sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/tv2"
            android:padding="10dp"
            android:textSize="20sp"
            android:text="二货_无法长大"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>
</LinearLayout>

//主Activity

public class MainActivity extends FragmentActivity implements MainActivityViewListener{
    private ListPresenter presenter;
    private List<Bean.RetBean.ListBean>list;
    private RecyclerView thirdRecyclerview;
    private MyAdapter myAdapter;
    //下载
    private int max;
    private TextView total;
    private ProgressBar mProgressBar;
    private DownloadUtil mDownloadUtil;
    private static final String TAG = MainActivity.class.getSimpleName();
    private String urlString;
    //长度
    private Handler handler = new Handler();
    int pro=0;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Fresco.initialize(this);
        setContentView(R.layout.activity_main);
        initView();
        urlString = "http://phonemovie.ks3-cn-beijing.ksyun.com/image/2017/10/16/1508141676941055287.jpg";
        String localPath = Environment.getExternalStorageDirectory()
                .getAbsolutePath() + "/local";
        mDownloadUtil = new DownloadUtil(2, localPath, "ab.jpg", urlString,
                this);
        mDownloadUtil.setOnDownloadListener(new DownloadUtil.OnDownloadListener() {
            @Override
            public void downloadStart(int fileSize) {
                // TODO Auto-generated method stub
                Log.w(TAG, "fileSize::" + fileSize);
                max = fileSize;
                mProgressBar.setMax(fileSize);
            }
            @Override
            public void downloadProgress(int downloadedSize) {
                Log.w(TAG, "Compelete::" + downloadedSize);
                mProgressBar.setProgress(downloadedSize);
                total.setText((int) downloadedSize * 100 / max + "%");
            }
            @Override
            public void downloadEnd() {
                Log.w(TAG, "ENd");
            }
        });
    }
    private void initView() {
        thirdRecyclerview = findViewById(R.id.third_recyclerview);
        thirdRecyclerview.setLayoutManager(new LinearLayoutManager(this));
        myAdapter=new MyAdapter(MainActivity.this,list);
        presenter = new ListPresenter(this);
        thirdRecyclerview.setAdapter(myAdapter);
        presenter.loadList();
        myAdapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                mDownloadUtil.start();
                handler.post(runnable); //开始执行

                Toast.makeText(MainActivity.this,"开始",Toast.LENGTH_LONG).show();
            }
        });
        myAdapter.setOnItemLongClickListener(new MyAdapter.OnRecyclerItemLongListener() {
            @Override
            public void onItemLongClick(View view, int position) {
                mDownloadUtil.pause();
                Toast.makeText(MainActivity.this,"暂停",Toast.LENGTH_LONG).show();
            }
        });



        //下载
        total= (TextView) findViewById(R.id.textView);
        mProgressBar= (ProgressBar) findViewById(R.id.progressBar);
    }

    //启动子线程进度完之后跳转
    Runnable runnable=new Runnable() {
        @Override
        public void run() {
            mProgressBar.setVisibility(View.VISIBLE);
            pro=mProgressBar.getProgress()+100;
            mProgressBar.setProgress(pro);
            //如果进度小于100,,则延迟1000毫秒后重复执行runnable
            if(pro<100){
                handler.postDelayed(runnable, 100);
            }else{
                mProgressBar.setVisibility(View.GONE);
                startActivity(new Intent(MainActivity.this, Main2Activity.class));
                handler.removeCallbacks(runnable);
                mProgressBar.setProgress(0);
            }
        }
    };
    @Override
    public void ShowData(Bean bean) {

        myAdapter.setData(bean);
    }
}

//主布局

<LinearLayout
    android:orientation="vertical"
    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" tools:context="com.bawei.mythetests.MainActivity">

   <android.support.v7.widget.RecyclerView
       android:layout_width="match_parent"
       android:layout_weight="1"
       android:layout_height="match_parent"
       android:id="@+id/third_recyclerview"

     />
   <TextView
       android:id="@+id/textView"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentLeft="true"
       android:layout_alignParentStart="true"
       android:layout_alignParentTop="true"
       android:layout_marginLeft="23dp"
       android:layout_marginStart="23dp"
       android:layout_marginTop="18dp"
       android:text="TextView" />

   <ProgressBar
       android:id="@+id/progressBar"
       style="?android:attr/progressBarStyleHorizontal"
       android:layout_width="fill_parent"
       android:layout_height="7.5dp"
       android:max="100"
       android:progress="100"
       android:layout_marginRight="8dp"
       android:layout_below="@+id/textView"
       android:visibility="visible"/>
</LinearLayout>

//接口

public interface OnFinish {
    void finish(Bean bean);


}

//Main2类

public class Main2Activity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        VideoView vv=(VideoView) findViewById(R.id.videoView1);
        //设置播放路径
        ///data/media/0/local/abc.MP4
        ///data/iToolsVMShare/minion_09.mp4
        vv.setVideoPath("data/media/0/local/abc.MP4");
        MediaController control=new MediaController(this);
        control.setMediaPlayer(vv);
        vv.setMediaController(control);
        //开始播放
        vv.start();
    }
}

//Main2布局

 <VideoView
        android:id="@+id/videoView1"
        android:layout_width="match_parent"
        android:layout_height="200dp"
/>

//断点续传

public class DownlaodSqlTool {

    private DownLoadHelper dbHelper;
    public DownlaodSqlTool(Context context){
        dbHelper=new DownLoadHelper(context);

    }
    /**
     * 创建下载的具体信息
     */
    public void insertInfos(List<DownloadInfo> infos) {
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        for (DownloadInfo info : infos) {
            String sql = "insert into download_info(thread_id,start_pos, end_pos,compelete_size,url) values (?,?,?,?,?)";
            Object[] bindArgs = { info.getThreadId(), info.getStartPos(),
                    info.getEndPos(), info.getCompeleteSize(), info.getUrl() };
            database.execSQL(sql, bindArgs);
        }
    }
    /**
     * 得到下载具体信息
     */
    public List<DownloadInfo> getInfos(String urlstr) {
        List<DownloadInfo> list = new ArrayList<DownloadInfo>();
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        String sql = "select thread_id, start_pos, end_pos,compelete_size,url from download_info where url=?";
        Cursor cursor = database.rawQuery(sql, new String[] { urlstr });
        while (cursor.moveToNext()) {
            DownloadInfo info = new DownloadInfo(cursor.getInt(0),
                    cursor.getInt(1), cursor.getInt(2), cursor.getInt(3),
                    cursor.getString(4));
            list.add(info);
        }
        return list;
    }

    /**
     * 更新数据库中的下载信息
     */
    public void updataInfos(int threadId, int compeleteSize, String urlstr) {
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        String sql = "update download_info set compelete_size=? where thread_id=? and url=?";
        Object[] bindArgs = { compeleteSize, threadId, urlstr };
        database.execSQL(sql, bindArgs);
    }
    /**
     * 关闭数据库
     */
    public void closeDb() {
        dbHelper.close();
    }

    /**
     * 下载完成后删除数据库中的数据
     */
    public void delete(String url) {
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        database.delete("download_info", "url=?", new String[] { url });
    }
}

//断点续传

public class DownLoadHelper extends SQLiteOpenHelper {
    private static final String SQL_NAME = "download.db";
    private static final int DOWNLOAD_VERSION=1;
    public DownLoadHelper(Context context) {
        super(context, SQL_NAME, null, DOWNLOAD_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table download_info(_id integer PRIMARY KEY AUTOINCREMENT, thread_id integer, "
                + "start_pos integer, end_pos integer, compelete_size integer,url char)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}

//断点续传

public class DownloadHttpTool {
    /**
     *
     * 利用Http协议进行多线程下载具体实践类
     */
    private static final String TAG = DownloadHttpTool.class.getSimpleName();
    private int threadCount;//线程数量
    private String urlstr;//URL地址
    private Context mContext;
    private Handler mHandler;
    private List<DownloadInfo> downloadInfos;//保存下载信息的类
    private String localPath;//目录
    private String fileName;//文件名
    private int fileSize;
    private DownlaodSqlTool sqlTool;//文件信息保存的数据库操作类
    private enum Download_State {
        Downloading, Pause, Ready;//利用枚举表示下载的三种状态
    }
    private Download_State state = Download_State.Ready;//当前下载状态

    private int globalCompelete = 0;//所有线程下载的总数

    public DownloadHttpTool(int threadCount, String urlString,
                            String localPath, String fileName, Context context, Handler handler) {
        super();
        this.threadCount = threadCount;
        this.urlstr = urlString;
        this.localPath = localPath;
        this.mContext = context;
        this.mHandler = handler;
        this.fileName = fileName;
        sqlTool = new DownlaodSqlTool(mContext);
    }

    //在开始下载之前需要调用ready方法进行配置
    public void ready() {
        Log.w(TAG, "ready");
        globalCompelete = 0;
        downloadInfos = sqlTool.getInfos(urlstr);
        if (downloadInfos.size() == 0) {
            initFirst();
        } else {
            File file = new File(localPath + "/" + fileName);
            if (!file.exists()) {
                sqlTool.delete(urlstr);
                initFirst();
            } else {
                fileSize = downloadInfos.get(downloadInfos.size() - 1)
                        .getEndPos();
                for (DownloadInfo info : downloadInfos) {
                    globalCompelete += info.getCompeleteSize();
                }
                Log.w(TAG, "globalCompelete:::" + globalCompelete);
            }
        }
    }

    public void start() {
        Log.w(TAG, "start");
        if (downloadInfos != null) {
            if (state == Download_State.Downloading) {
                return;
            }
            state = Download_State.Downloading;
            for (DownloadInfo info : downloadInfos) {
                Log.v(TAG, "startThread");
                new DownloadThread(info.getThreadId(), info.getStartPos(),
                        info.getEndPos(), info.getCompeleteSize(),
                        info.getUrl()).start();
            }
        }
    }

    public void pause() {
        state = Download_State.Pause;
        sqlTool.closeDb();
    }

    public void delete(){
        compelete();
        File file = new File(localPath + "/" + fileName);
        file.delete();
    }

    public void compelete() {
        sqlTool.delete(urlstr);
        sqlTool.closeDb();
    }

    public int getFileSize() {
        return fileSize;
    }

    public int getCompeleteSize() {
        return globalCompelete;
    }

    //第一次下载初始化
    private void initFirst() {
        Log.w(TAG, "initFirst");
        try {
            URL url = new URL(urlstr);
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection();
            connection.setConnectTimeout(5000);
            connection.setRequestMethod("GET");
            fileSize = connection.getContentLength();
            Log.w(TAG, "fileSize::" + fileSize);
            File fileParent = new File(localPath);
            if (!fileParent.exists()) {
                fileParent.mkdir();
            }
            File file = new File(fileParent, fileName);
            if (!file.exists()) {
                file.createNewFile();
            }
            // 本地访问文件
            RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
            accessFile.setLength(fileSize);
            accessFile.close();
            connection.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
        int range = fileSize / threadCount;
        downloadInfos = new ArrayList<DownloadInfo>();
        for (int i = 0; i < threadCount - 1; i++) {
            DownloadInfo info = new DownloadInfo(i, i * range, (i + 1) * range
                    - 1, 0, urlstr);
            downloadInfos.add(info);
        }
        DownloadInfo info = new DownloadInfo(threadCount - 1, (threadCount - 1)
                * range, fileSize - 1, 0, urlstr);
        downloadInfos.add(info);
        sqlTool.insertInfos(downloadInfos);
    }
    //自定义下载线程
    private class DownloadThread extends Thread {

        private int threadId;
        private int startPos;
        private int endPos;
        private int compeleteSize;
        private String urlstr;
        private int totalThreadSize;

        public DownloadThread(int threadId, int startPos, int endPos,
                              int compeleteSize, String urlstr) {
            this.threadId = threadId;
            this.startPos = startPos;
            this.endPos = endPos;
            totalThreadSize = endPos - startPos + 1;
            this.urlstr = urlstr;
            this.compeleteSize = compeleteSize;
        }

        @Override
        public void run() {
            HttpURLConnection connection = null;
            RandomAccessFile randomAccessFile = null;
            InputStream is = null;
            try {
                randomAccessFile = new RandomAccessFile(localPath + "/"
                        + fileName, "rwd");
                randomAccessFile.seek(startPos + compeleteSize);
                URL url = new URL(urlstr);
                connection = (HttpURLConnection) url.openConnection();
                connection.setConnectTimeout(5000);
                connection.setRequestMethod("GET");
                connection.setRequestProperty("Range", "bytes="
                        + (startPos + compeleteSize) + "-" + endPos);
                is = connection.getInputStream();
                byte[] buffer = new byte[1024];
                int length = -1;
                while ((length = is.read(buffer)) != -1) {
                    randomAccessFile.write(buffer, 0, length);
                    compeleteSize += length;
                    Message message = Message.obtain();
                    message.what = threadId;
                    message.obj = urlstr;
                    message.arg1 = length;
                    mHandler.sendMessage(message);
                    sqlTool.updataInfos(threadId, compeleteSize, urlstr);
                    Log.w(TAG, "Threadid::" + threadId + "    compelete::"
                            + compeleteSize + "    total::" + totalThreadSize);
                    if (compeleteSize >= totalThreadSize) {
                        break;
                    }
                    if (state != Download_State.Downloading) {
                        break;
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (is != null) {
                        is.close();
                    }
                    randomAccessFile.close();
                    connection.disconnect();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

//断点续传

public class DownloadInfo {
    /**
     * 保存每个下载线程下载信息类
     * 
     */
    private int threadId;// 下载器id
    private int startPos;// 开始点
    private int endPos;// 结束点
    private int compeleteSize;// 完成度
    private String url;// 下载文件的URL地址
    public DownloadInfo(int threadId, int startPos, int endPos,
            int compeleteSize, String url) {
        this.threadId = threadId;
        this.startPos = startPos;
        this.endPos = endPos;
        this.compeleteSize = compeleteSize;
        this.url = url;
    }
    public DownloadInfo() {
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public int getThreadId() {
        return threadId;
    }

    public void setThreadId(int threadId) {
        this.threadId = threadId;
    }

    public int getStartPos() {
        return startPos;
    }

    public void setStartPos(int startPos) {
        this.startPos = startPos;
    }

    public int getEndPos() {
        return endPos;
    }

    public void setEndPos(int endPos) {
        this.endPos = endPos;
    }

    public int getCompeleteSize() {
        return compeleteSize;
    }

    public void setCompeleteSize(int compeleteSize) {
        this.compeleteSize = compeleteSize;
    }

    @Override
    public String toString() {
        return "DownloadInfo [threadId=" + threadId + ", startPos=" + startPos
                + ", endPos=" + endPos + ", compeleteSize=" + compeleteSize
                + "]";
    }
}

//断点续传

public class DownloadUtil {
 
    private DownloadHttpTool mDownloadHttpTool;
    private OnDownloadListener onDownloadListener;
 
    private int fileSize;
    private int downloadedSize = 0;
 
    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
 
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            super.handleMessage(msg);
            int length = msg.arg1;
            synchronized (this) {//加锁保证已下载的正确性
                downloadedSize += length;
            }
            if (onDownloadListener != null) {
                onDownloadListener.downloadProgress(downloadedSize);
            }
            if (downloadedSize >= fileSize) {
                mDownloadHttpTool.compelete();
                if (onDownloadListener != null) {
                    onDownloadListener.downloadEnd();
                }
            }
        }
 
    };
 
    public DownloadUtil(int threadCount, String filePath, String filename,
            String urlString, Context context) {
 
        mDownloadHttpTool = new DownloadHttpTool(threadCount, urlString,
                filePath, filename, context, mHandler);
    }



    //下载之前首先异步线程调用ready方法获得文件大小信息,之后调用开始方法
    public void start() {
        new AsyncTask<Void,Void,Void>() {
 
            @Override
            protected Void doInBackground(Void... arg0) {
                // TODO Auto-generated method stub
                mDownloadHttpTool.ready();
                return null;
            }
 
            @Override
            protected void onPostExecute(Void result) {
                // TODO Auto-generated method stub
                super.onPostExecute(result);
                fileSize = mDownloadHttpTool.getFileSize();
                downloadedSize = mDownloadHttpTool.getCompeleteSize();
                Log.w("Tag", "downloadedSize::" + downloadedSize);
                if (onDownloadListener != null) {
                    onDownloadListener.downloadStart(fileSize);
                }
                mDownloadHttpTool.start();
            }
        }.execute();
    }
 
    public void pause() {
        mDownloadHttpTool.pause();
    }
     
    public void delete(){
        mDownloadHttpTool.delete();
    }
 
    public void reset(){
        mDownloadHttpTool.delete();
        start();
    }
     
    public void setOnDownloadListener(OnDownloadListener onDownloadListener) {
        this.onDownloadListener = onDownloadListener;
    }
 
    //下载回调接口
    public interface OnDownloadListener {
        public void downloadStart(int fileSize);
 
        public void downloadProgress(int downloadedSize);//记录当前所有线程下总和
 
        public void downloadEnd();
    }
}

//权限

 <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.INTERNET"/>

//依赖

compile 'com.android.support:appcompat-v7:26.+'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    compile 'com.squareup.retrofit2:retrofit:2.0.1'
    compile 'com.squareup.retrofit2:converter-gson:2.0.1'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.0.1'
    compile 'io.reactivex:rxandroid:1.1.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
    compile 'com.android.support:recyclerview-v7:26.+'
    compile 'com.facebook.fresco:fresco:0.9.0+'
    compile 'com.jakewharton:butterknife:8.8.1'
    testCompile 'junit:junit:4.12'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
原文地址:https://www.cnblogs.com/yu12/p/7877917.html