MVP+ReRxGreenDao多线程下载

来源:互联网 发布:a计划软件 编辑:程序博客网 时间:2024/06/08 06:53

依赖:

GreenDao:

classpath 'org.greenrobot:greendao-gradle-plugin:3.2.1'
apply plugin: 'org.greenrobot.greendao'
compile 'org.greenrobot:greendao:3.2.0'
其他依赖:4

    compile 'io.reactivex.rxjava2:rxjava:2.1.1'    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'    //retrofit    compile 'com.squareup.retrofit2:retrofit:2.2.0'    //Gson converter    compile 'com.squareup.retrofit2:converter-gson:2.2.0'    //RxJava2 Adapter    compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'    //okhttp    compile 'com.squareup.okhttp3:okhttp:3.6.0'    implementation 'com.android.support:recyclerview-v7:26.1.0'    compile 'com.youth.banner:banner:1.4.9'    compile 'com.github.bumptech.glide:glide:3.7.0'    compile 'com.facebook.fresco:fresco:0.11.0'


Retrofit注解:

public interface GetInterface {    @Streaming    @GET//我们在下载的时候,需要加入Range值,用来标记下载的点 Observable<ResponseBody> download(@Header("RANGE") String start, @Url String url);}
封装Retrofit:

public class BaseService {//实现ok,在很多应用的时候,会出现添加拦截器请求数据    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();    private static Retrofit.Builder builder =            new Retrofit.Builder()//Base.url 是我们自己定义的基路径                                      .baseUrl(Base.url)//支持GSON和RXJAVA                   .addConverterFactory(GsonConverterFactory.create())                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create());//提供一个方法来实现retrofit的创建    public static <S> S createService(Class<S> serviceClass) {        Retrofit retrofit = builder.client(httpClient.build()).build();        return retrofit.create(serviceClass);    }}

Model接口:

public interface IDwonFile {//实现获取数据的方法,start开始的位置,url是我们请求的路径,url2是我们要缓冲的路径,GetCallback     是实现接口回调   void getData(String start, String url, String url2, GetCallback callback);    interface GetCallback {        void GetComplete(ResponseBody responseBody);    }//暂停的方法    void stop();//继续的方法    void jixu();//获取进度条值的方法    void getProgress();}

Model实现类:

public class IdownModel implements IDwonFile {    private static final String DOWNLOAD_INIT = "1";    private static final String DOWNLOAD_ING = "2";    private static final String DOWNLOAD_PAUSE = "3";    public getProgress getProgress;    private String stateDownload = DOWNLOAD_ING;//当前线程状态    String url3 = "";    Context context;    private long l;    public IdownModel(Context context) {        this.context = context;    }    @Override    public void getData(String start, String url, final String url2, final GetCallback callback) {        this.url3 = url;        BaseService.createService(GetInterface.class).download(start, url3)                .subscribeOn(Schedulers.io())                .observeOn(AndroidSchedulers.mainThread())                .subscribe(new Observer<ResponseBody>() {                    @Override                    public void onSubscribe(Disposable d) {                    }                    @Override                    public void onNext(ResponseBody responseBody) {                        l = responseBody.contentLength();                        Log.i("=====length=====", "onNext: " + l);                        downloadFile(l, url2);                    }                    @Override                    public void onError(Throwable e) {                    }                    @Override                    public void onComplete() {                    }                });    }    @Override    public void stop() {        stateDownload = DOWNLOAD_PAUSE;    }    @Override    public void jixu() {        stateDownload = DOWNLOAD_ING;    }    @Override    public void getProgress() {    }    public void downloadFile(long length, String url2) {        final File file = new File(url2);        if (!file.exists()) {            try {                file.createNewFile();            } catch (IOException e) {                e.printStackTrace();            }        }        int threadNum = 5;        long blockSize = length / threadNum;        long startPosition = 0;        long end = 0;//        //四舍五入---  让一个数字+0。5在四舍五入 就变成 向上取整        //计算出下载块以后   创建线程执行下载操作        for (int i = 0; i < threadNum; i++) {            List<Bean2> cityInfoList = DBHelper.getInstance(context).getCityInfoList(i);            if (cityInfoList.size() > 0) {                Long range = cityInfoList.get(0).getRange();                Long start = cityInfoList.get(0).getStart();                Long end1 = cityInfoList.get(0).getEnd();                startPosition = range + start;                end = end1;                Log.i("=====", "downloadFile: " + startPosition + "==" + end);            } else {                startPosition = blockSize * i;                //让最后一个线程下载的大小是正好的,  总长度 - 除了最后一个块的大小和                if (i == threadNum - 1) {                    blockSize = length - blockSize * (threadNum - 1);                }                end = startPosition + blockSize - 1;                Bean2 bean2 = new Bean2();                bean2.setThreadNum(i + "");                bean2.setRange((long) 0);                bean2.setStart(startPosition);                bean2.setEnd(end);                DBHelper.getInstance(context).addToCityInfoTable(bean2);            }            downloadTask(startPosition, file, end, length, i);        }    }    public void downloadTask(final long startPosition, final File file, long end, final long length, final int i) {        //计算开始位置        String range = "bytes=" + startPosition + "-" + end;        BaseService.createService(GetInterface.class).download(range, url3)                .subscribeOn(Schedulers.io())                .observeOn(Schedulers.io())                .subscribe(new Observer<ResponseBody>() {                    @Override                    public void onSubscribe(Disposable d) {                    }                    @Override                    public void onNext(ResponseBody responseBody) {                        BufferedInputStream bis = null;                        RandomAccessFile raf = null;                        try {                            bis = new BufferedInputStream(responseBody.byteStream());                            raf = new RandomAccessFile(file, "rwd");                            raf.seek(startPosition);                             byte[] buff = new byte[1024 * 8];                            int len = 0;                            List<Bean2> cityInfoList = DBHelper.getInstance(context).getCityInfoList(i);                            long length2 = cityInfoList.get(0).getRange();                            Log.i("=====继续length2=======", "onNext: " + length2);                            while ((len = bis.read(buff)) != -1) {                                Log.i("===循环继续====", "onNext: ");                                if (stateDownload == DOWNLOAD_ING) {                                    Log.i("===继续下载====", "onNext: ");                                    length2 += len;                                    raf.write(buff, 0, len);                                    handler.sendEmptyMessage((int) len);                                } else if (stateDownload == DOWNLOAD_PAUSE) {                                    //更新数据库                                    DBHelper.getInstance(context).updateInfo(i, length2);                                    break;                                }                            }                        } catch (IOException e) {                            e.printStackTrace();                        } finally {                            if (bis != null) {                                try {                                    bis.close();                                } catch (IOException e) {                                    e.printStackTrace();                                }                            }                            if (raf != null) {                                try {                                    raf.close();                                } catch (IOException e) {                                    e.printStackTrace();                                }                            }                        }                    }                    @Override                    public void onError(Throwable e) {                    }                    @Override                    public void onComplete() {                    }                });    }    public void setGetProgress(IdownModel.getProgress getProgress) {        this.getProgress = getProgress;    }    public interface getProgress {        void getProgress_length(long l);    }    private long downloadedSize = 0;    @SuppressLint("HandlerLeak")    Handler handler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            //每次每个线程回来的长度            int length = msg.what;            synchronized (this) {                downloadedSize += length;            }            getProgress.getProgress_length(downloadedSize * 100 / l);            Log.i("downloadedSize", "handleMessage: " + downloadedSize);            Log.i("百分比", "handleMessage: " + downloadedSize * 100 / l);        }    };}


View接口:
public interface IDownView {    void getData(ResponseBody responseBody);    void getPro(long length);}


P层:

public class DownPresenter implements IPresenter<IDownView> {    SoftReference<IDownView> srf;    IdownModel model;    Context context;    public DownPresenter(IDownView view, Context context) {        this.context = context;        model = new IdownModel(context);        attch(view);    }    public void down(final String start, final String url, final String url2) {        model.getData(start, url, url2, new IDwonFile.GetCallback() {            @Override            public void GetComplete(ResponseBody responseBody) {            }        });    }    public void stop(){        model.stop();    }    public void jixu(){        model.jixu();    }    public void setProgress(){       model.setGetProgress(new IdownModel.getProgress() {           @Override           public void getProgress_length(long l) {                srf.get().getPro(l);           }       });    }    @Override    public void attch(IDownView view) {        srf = new SoftReference<IDownView>(view);    }    @Override    public void disattch() {    }}


基类:

public  interface IPresenter<T> {    void attch(T view);    void disattch();}public abstract class BaseActivity<T extends IPresenter> extends AppCompatActivity {    public T presenter;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        createPresnter();    }    protected abstract void createPresnter();    protected abstract void init();}



GreenDao:

public class DBHelper {    private static Context mContext;    private static DBHelper instance;    Bean2Dao bean2Dao;    Bean2 bean;    private DBHelper() {    }    public static DBHelper getInstance(Context context) {        if (instance == null) {            instance = new DBHelper();            if (mContext == null) {                mContext = context;            }            // 数据库对象            // 数据库对象            DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(mContext, "student.db", null);            DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDb());            DaoSession daoSession = daoMaster.newSession();            instance.bean2Dao = daoSession.getBean2Dao();        }        return instance;    }    /** 添加数据 */    public void addToCityInfoTable(Bean2 item)    {        bean2Dao.insert(item);    }    /** 查询 */    /** 通过城市id查找其类型id */    public List<Bean2> getCityInfoList(int threadNum) {        QueryBuilder<Bean2> qb = bean2Dao.queryBuilder();        qb.where(Bean2Dao.Properties.ThreadNum.eq(threadNum));        List<Bean2> list = qb.list();        Log.i("========", "getCityInfoList: " + list);        return list;    }    public void updateInfo(int id,long rang){        QueryBuilder<Bean2> qb = bean2Dao.queryBuilder();        qb.where(Bean2Dao.Properties.ThreadNum.eq(id));        List<Bean2> list = qb.list();        Bean2 bean2 = list.get(0);        bean2.setRange(rang);        bean2Dao.update(bean2);    }}


实现:
public class OtherActivity extends BaseActivity<DownPresenter> implements /*PlayerManager.PlayerStateListener,*/ View.OnClickListener, IDownView {    private String video_url;    private Button mBtn;    public static long MAX_SIZE;    private VideoView mWb;    private Button mStopBtn;    private Button mJxBtn;    private ProgressBar mPb;    private TextView mTv;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_other);        initView();        Intent intent = getIntent();        video_url = intent.getStringExtra("video_url");        Log.i("11111111111111111", "onCreate: " + video_url);            presenter.setProgress();    }    @Override    protected void createPresnter() {        presenter = new DownPresenter(this, this);    }    @Override    protected void init() {    }    private void initView() {           mBtn = (Button) findViewById(R.id.btn);        mBtn.setOnClickListener(this);          mStopBtn = (Button) findViewById(R.id.btn_stop);        mStopBtn.setOnClickListener(this);        mJxBtn = (Button) findViewById(R.id.btn_jx);        mJxBtn.setOnClickListener(this);        mPb = (ProgressBar) findViewById(R.id.pb);        mTv = (TextView) findViewById(R.id.tv);    }        @Override    public void onClick(View v) {        switch (v.getId()) {            case R.id.btn:                String url2 = getCacheDir() + "haha.mp4";                presenter.down(String.valueOf(0), url, url2);                break;            case R.id.btn_stop:// TODO 17/11/22                presenter.stop();                break;            case R.id.btn_jx:// TODO 17/11/22                String url3 = getCacheDir() + "haha.mp4";            presenter.jixu();                presenter.down(String.valueOf(0), url, url3);                break;            default:                break;        }    }    @Override    public void getData(ResponseBody responseBody) {    }    @Override    public void getPro(long length) {        mPb.setMax(100);        mPb.setProgress((int) length);        //mTv.setText(length+"%");    }}
布局:

 
 <Button        android:id="@+id/btn"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="下载" />        android:id="@+id/btn_stop"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_below="@+id/btn"        android:text="暂停" />    <Button        android:id="@+id/btn_jx"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_below="@+id/btn_stop"        android:text="继续" />    <ProgressBar        android:id="@+id/pb"        style="@style/Base.Widget.AppCompat.ProgressBar.Horizontal"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_below="@+id/btn_jx" />    <TextView        android:id="@+id/tv"        android:layout_width="wrap_content"        android:layout_below="@+id/pb"        android:layout_height="wrap_content" />

 
原创粉丝点击