集训day_08_3(多线程下载Android实现)

package activitytest.example.com.downandroid;

import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ProgressBar;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {


    EditText et_path;
    EditText et_threadCount;
    LinearLayout ll_pb;
    String path;
    int threadCount;
    List<ProgressBar> pblist;

    private static int runningThread;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //找到控件
        et_path = findViewById(R.id.et_path);
        et_threadCount = findViewById(R.id.et_threadCount);
        ll_pb = findViewById(R.id.ll_pb);

        //添加一个集合,用来存进度条的引用
        pblist = new ArrayList<ProgressBar>();

    }

    //实现点击下载逻辑
    public void click(View v){

        //【1----------】获取下载路径
        path = et_path.getText().toString().trim();
        //【2----------】获取线程数量
        String threadCountt = et_threadCount.getText().toString().trim();
        threadCount = Integer.parseInt(threadCountt);
        //【3----------】先把之前的进度条移除再添加进度条
        ll_pb.removeAllViews();
        //【4----------】动态的根据线程数量添加进度条
        pblist.clear();
        for(int i = 0 ; i< threadCount ; i++){
            //把定义的item布局转换成一个View对象
            ProgressBar pbView = (ProgressBar) View.inflate(getApplicationContext(),R.layout.item,null);

            //把pbView添加到集合中
            pblist.add(pbView);

            //添加进度条
            ll_pb.addView(pbView);
        }


        //【5----------】开始移植  因为联网,所以要创建一个子线程
        new Thread(){
            @Override
            public void run() {
                try {
                    URL url = new URL(path);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("GET");
                    conn.setConnectTimeout(5000);
                    int code = conn.getResponseCode();
                    if (code == 200) {
                        int length = conn.getContentLength();
                        runningThread = threadCount;
                        System.out.println("length:" + length);

                        RandomAccessFile rafAccessFile = new RandomAccessFile(
                                getFilename(path), "rw");
                        rafAccessFile.setLength(length);

                        int blockSize = length / threadCount;

                        for (int i = 0; i < threadCount; i++) {
                            int starIndex = i * blockSize; // 每个线程下载的开始位置
                            int endIndex = (i + 1) * blockSize - 1;// 每个线程下载的结束位置
                            // 特殊情况 就是最后一个线程
                            if (i == threadCount - 1) {
                                endIndex = length - 1;
                            }

                            new DownLoadThread(starIndex, endIndex, i).start();

                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }
    public String getFilename(String path) { // 获取文件的名字

        int start = path.lastIndexOf("/") + 1;
        String substring = path.substring(start);

        String fileName =MainActivity.this.getCacheDir().getPath()+"/"+substring;

        return fileName;
    }


    private class DownLoadThread extends Thread {

        private int starIndex;
        private int endIndex;
        private int threadId;

        private int PbMaxSize;  //代表当前线程下载的最大值
        private int pblastPostion;//如果中断过,获取上次下载的位置
        public DownLoadThread(int starIndex, int endIndex, int threadId) {
            this.starIndex = starIndex;
            this.endIndex = endIndex;
            this.threadId = threadId;
        }

        @Override
        public void run() {
            try {

                //【6----------】计算当前进度条的最大值
                PbMaxSize = endIndex - starIndex;

                URL url = new URL(path);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(5000);

                File file = new File(getFilename(path) + threadId + ".txt");
                if (file.exists() && file.length() > 0) {
                    FileInputStream fis = new FileInputStream(file);
                    BufferedReader bufr = new BufferedReader(new InputStreamReader(fis));
                    String lastPositionn = bufr.readLine(); // 读取出来的内容就是上次下载的位置
                    int lastPosition = Integer.parseInt(lastPositionn);

                    //给定义的进度条位置赋值
                    pblastPostion = lastPosition - starIndex;

                    starIndex = lastPosition +1;
                    fis.close();
                }

                conn.setRequestProperty("Range", "bytes=" + starIndex + "-"
                        + endIndex);

                int code = conn.getResponseCode();
                if (code == 206) { // 200表示获取服务器资源全部成功,206表示请求部分资源成功

                    RandomAccessFile raf = new RandomAccessFile(
                            getFilename(path), "rw");
                    raf.seek(starIndex);

                    InputStream in = conn.getInputStream(); // 存的是ttt.exe

                    int len = -1;
                    byte[] buffer = new byte[1024 * 1024];

                    int total = 0; // 代表当前线程下载的大小

                    while ((len = in.read(buffer)) != -1) {
                        raf.write(buffer, 0, len);

                        total += len;
                        int currentThreadPosition = starIndex + total;
                        RandomAccessFile raff = new RandomAccessFile(getFilename(path) + threadId + ".txt", "rwd");
                        raff.write(String.valueOf(currentThreadPosition).getBytes());
                        raff.close();

                        //设置一下当前进度条的最大值和当前进度
                        pblist.get(threadId).setMax(PbMaxSize); //设置进度条的最大值
                        pblist.get(threadId).setProgress(pblastPostion+total);//设置进度条的当前位置
                    }
                    raf.close();// 释放资源

                    System.out.println("线程:" + threadId + "--下载完了");
                    synchronized (DownLoadThread.class) {
                        runningThread--;
                        if (runningThread == 0) { // 说明所有线程都执行完毕了
                            for (int i = 0; i < threadCount; i++) {
                                File deleFile = new File(getFilename(path) + i+ ".txt");
                                deleFile.delete();
                            }
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/depths_p/article/details/81226989