MVP Retrofit多线程下载

来源:互联网 发布:淘宝网休闲裤子 编辑:程序博客网 时间:2024/05/18 03:45

多线程下载:
目的:最大限度的利用CPU资源
过程:
1.获得下载文件的长度,然后设置本地文件长度
2.根据文件长度和线程数计算每条线程下载的数据长度和下载位置
3.使用HTTP的range字段指定每条线程从什么位置下载,到什么位置停止
4.保存文件。使用RandomAccessFile类指定每条线程从本地文件的什么位置开始写入数据。
首先先看一下依赖

    compile 'com.youth.banner:banner:1.4.9'    compile 'com.github.bumptech.glide:glide:3.7.0'    compile 'com.jcodecraeer:xrecyclerview:1.3.2'    compile 'io.reactivex:rxjava:1.0.14'    compile 'io.reactivex:rxandroid:1.0.1'    compile 'com.squareup.retrofit2:retrofit:2.0.2'    compile 'com.squareup.okhttp3:okhttp:3.1.2'    compile 'com.squareup.retrofit2:converter-gson:2.0.2'    compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'

用MVP模式首先看View层

接口类public interface IDialogView {    public void showDialog();}

再看MODEL层

接口类public interface IDownLoadModel {    public IDataView downLoad();}
public class DownLoadModel implements IDownLoadModel {    @Override    public IDataView downLoad() {        Retrofit retrofit=new Retrofit.Builder()                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())                .addConverterFactory(GsonConverterFactory.create())                .baseUrl("http://10.0.2.2:8080/")                .build();        IDataView dataView = retrofit.create(IDataView.class);        return dataView;    }}

PRESENTER层

public abstract class BaseActivity<T extends IDataPresenter> extends AppCompatActivity {    public T presenter;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        createPresenter();    }    public abstract void createPresenter();    @Override    protected void onDestroy() {        super.onDestroy();        if (presenter!=null){            presenter.detach();        }    }}
public interface IDataPresenter<T> {    public void attach(T view);    public void detach();}
public class DownLoadPresenter implements IDataPresenter<IDialogView> {    DownLoadModel model;    SoftReference<IDialogView> softView;    public DownLoadPresenter(IDialogView view) {        attach(view);        model = new DownLoadModel();    }    public void getDataLength(final String downLoadUrl, final String path, final long threadNum) {        model.downLoad().getFileLength(downLoadUrl)                .subscribeOn(Schedulers.io())                .observeOn(Schedulers.io())                .subscribe(new Observer<ResponseBody>() {                    @Override                    public void onCompleted() {                    }                    @Override                    public void onError(Throwable e) {                    }                    @Override                    public void onNext(ResponseBody responseBody) {                        long length = responseBody.contentLength();                        DownLoadTask.getDownLoadData(DownLoadPresenter.this, downLoadUrl, path, length, threadNum);                    }                });    }    public void getDownLoadFile(String downLoadUrl, String range, final File file, final long startPosition) {        model.downLoad().downLoadFile(downLoadUrl, range)                .subscribeOn(Schedulers.io())                .observeOn(Schedulers.io())                .subscribe(new Observer<ResponseBody>() {                    @Override                    public void onCompleted() {                    }                    @Override                    public void onError(Throwable e) {                    }                    @Override                    public void onNext(ResponseBody responseBody) {//                    Log.i("+++++++++++++++++", "onResponse: "+response.body().contentLength());                        BufferedInputStream bis = new BufferedInputStream(responseBody.byteStream());                        try {                            RandomAccessFile raf = new RandomAccessFile(file, "rwd");                            raf.seek(startPosition);                            byte[] buff = new byte[1024 * 8];                            int len = 0;                            while ((len = bis.read(buff)) != -1) {                                raf.write(buff, 0, len);                            }                        } catch (Exception e) {                            e.printStackTrace();                        }                    }                });    }    @Override    public void attach(IDialogView view) {        softView = new SoftReference<IDialogView>(view);    }    @Override    public void detach() {        softView.clear();    }}
public interface IDataView {    @Streaming    @POST("{fileName}")    Observable<ResponseBody> getFileLength(@Path("fileName") String fileName);    @Streaming    @POST("{fileName}")    Observable<ResponseBody> downLoadFile(@Path("fileName") String fileName, @Header("Range") String range);}
public class DownLoadThread{    private String downLoadUrl;    private String path;    private long threadNum;    private DownLoadPresenter presenter;    public DownLoadThread(String downLoadUrl, String path, long threadNum,DownLoadPresenter presenter) {        this.downLoadUrl = downLoadUrl;        this.path = path;        this.threadNum = threadNum;        this.presenter=presenter;    }   public void show(){       presenter.getDataLength(downLoadUrl,path,threadNum);   }}
public class DownLoadFileThread extends Thread {    DownLoadPresenter presenter;    private String downLoadUrl;    private String range;    private File file;    private long startPosition;    public DownLoadFileThread(DownLoadPresenter presenter, String downLoadUrl, String range, File file, long startPosition) {        this.presenter = presenter;        this.downLoadUrl = downLoadUrl;        this.range = range;        this.file = file;        this.startPosition = startPosition;    }    @Override    public void run() {        presenter.getDownLoadFile(downLoadUrl,range,file,startPosition);    }}
public class DownLoadTask {    public static void getDownLoadData(DownLoadPresenter presenter,String downLoadUrl, String path, long length, long threadNum){        File file=new File(path);        if (!file.exists()){            try {                file.createNewFile();            } catch (IOException e) {                e.printStackTrace();            }        }        long blockSize=length/threadNum;        for (int i = 0; i < threadNum; i++) {            long startPosition=blockSize*i;            if (i==threadNum-1){                blockSize=length-blockSize*(threadNum-1);                Log.i("+++++++++++", "getDownLoadData: "+blockSize);            }            String range = "bytes=" + startPosition + "-" + (startPosition + blockSize - 1);            Log.i("++++++++++++++", "downLoadTask: "+startPosition+"-----"+(startPosition+blockSize-1));            new DownLoadFileThread(presenter,downLoadUrl,range,file,startPosition).start();        }    }}
public class MainActivity extends BaseActivity<DownLoadPresenter> implements IDialogView {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initData();    }    private void initData() {        showDialog();        Log.i("---------", "initData: "+presenter);    }    @Override    public void createPresenter() {        presenter=new DownLoadPresenter(this);    }    @Override    public void showDialog() {        Log.i("==============", "initData: "+presenter);        AlertDialog.Builder builder=new AlertDialog.Builder(this);        builder.setTitle("是否更新")                .setMessage("你太low了,赶快更新")                .setNegativeButton("取消",null)                .setPositiveButton("确定", new DialogInterface.OnClickListener() {                    @Override                    public void onClick(DialogInterface dialogInterface, int i) {                        new DownLoadThread("QQ.apk",getCacheDir()+"/qq.apk",5,presenter).show();                    }                }).show();    }}
原创粉丝点击