Android07

Android07

为什么多线程可以提高下载速度

对于同一个资源,开多个口子平均去下载,肯定是比一个口子从头下到尾块

多线程下载的步骤

  1. 客服端创建空白文件和服务器文件大小一样
  2. 开启n个线程,资源要等分
  3. 服务器下载完毕,多线程下载完毕

如何划分服务器的资源给不同的线程

每个线程需要下载的区块 int blocksize = totalLength/threadCount
线程0:0 - blocksize-1
线程1:blocksize - 2*blocksize-1
线程2:2*blocksize - 3*blocksize-1
线程n:n*blocksize - (n+1)*blocksize-1
最后一个是文件长度-1

多线程文件下载的实现

//告诉服务器 只想下载资源的一部分
conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);

RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rw");

raf.seek(startIndex);//每个线程写文件的开始位置都是不一样的.

@Override
    public void run() {
        try {
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //告诉服务器 只想下载资源的一部分
            conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
            InputStream is = conn.getInputStream();
            byte[] buffer = new byte[1024];
            int len = -1;
            RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rw");
            raf.seek(startIndex);//每个线程写文件的开始位置都是不一样的.
            while((len = is.read(buffer))!=-1){
                //把每个线程下载的数据放在自己的空间里面.
                raf.write(buffer,0, len);
            }
            raf.close();
            is.close();
            System.out.println("线程:"+threadId+"下载完毕了...");
        } catch (Exception e) {
            e.printStackTrace();
        }       }   }
/**
 * 获取一个文件名称
 */
public static String getFileName(String path){
    int start = path.lastIndexOf("/")+1;
    return path.substring(start);
}}

多线程断点下载的完成

currentPosition = startIndex;

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

f.renameTo(new File(threadId+".position.finish"));

public DownloadThread(int threadId, int startIndex, int endIndex) {
    this.threadId = threadId;
    this.startIndex = startIndex;
    this.endIndex = endIndex;
    System.out.println(threadId + "号线程下载的范围为:" + startIndex
            + "   ~~   " + endIndex);
    currentPosition = startIndex;
}

if(info.exists()&&info.length()>0){
    FileInputStream fis = new FileInputStream(info);
    BufferedReader br = new BufferedReader(new InputStreamReader(fis));
    currentPosition = Integer.valueOf(br.readLine());
    conn.setRequestProperty("Range", "bytes="+currentPosition+"-"+endIndex);
            System.out.println("原来有下载进度,从上一次终止的位置继续下载"
            +"bytes="+currentPosition+"-"+endIndex);
    fis.close();
    raf.seek(currentPosition);//每个线程写文件的开始位置都是不一样的.
}else{
//告诉服务器 只想下载资源的一部分
    conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
    System.out.println("原来没有有下载进度,新的下载"+ "bytes="+startIndex+"-"+endIndex);
    raf.seek(startIndex);//每个线程写文件的开始位置都是不一样的.
            }

多线程断点下载的小细节

public static int runningThreadCount ;

runningThreadCount = threadCount;

synchronized (MultiDownloader.class) {
                runningThreadCount--;
                if(runningThreadCount<=0){
                    for(int i=0;i<threadCount;i++){
                        File ft = new File(i+".position.finish");
                        ft.delete();
                    }                   
}           

多线程断点下载的移植

  1. SD卡的路径

    RandomAccessFile raf = new RandomAccessFile(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+getFileName(path), "rw");
    
  2. SD卡的权限

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    
  3. 子线程访问网络

    new Thread(){
    public void run() {
    访问网络的套路
    }
    }.start(); }

开源项目实现多线程断点下载

  1. 导包
    xUtils.jar

  2. 代码实现

    HttpUtils http = new HttpUtils();
        http.download(path, "/mnt/sdcard/xxx.exe", true, new RequestCallBack<File>() {
    
            @Override
            public void onSuccess(ResponseInfo<File> arg0) {
                Toast.makeText(MainActivity.this, "下载成功", 0).show();
            }
    
            @Override
            public void onLoading(long total, long current, boolean isUploading) {
                pb0.setMax((int) total);
                pb0.setProgress((int) current);
                super.onLoading(total, current, isUploading);
            }
    
            @Override
            public void onFailure(HttpException arg0, String arg1) {
                Toast.makeText(MainActivity.this, "下载失败"+arg1, 0).show();
            }
        });
    
  3. 权限

    //网络权限和SDcard写权限
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    

多界面应用程序的开发

activity的创建步骤

  1. 写一个类继承Activity.重写onCreate方法
  2. 在清单文件的application节点下面配置 android:name
    ActivityNotFoundException
  3. 创建一个布局文件 res/layout
  4. onCreate设置布局 setContentView(R.layout.);

activity的跳转

  1. 创建意图的对象 Intent intent = new Intent();
  2. 设置意图的跳转方向 intent.setClass(context,OtherActivity.class);
  3. 开启意图 startActivity(intent);
  4. this.finish();

人品计算器ui搭建

样式 android:theme="@style/AppTheme"

style.xml中
<style name="AppTheme" parent="AppBaseTheme">
    <!-- All customizations that are NOT specific to a particular API-level can go here. -->
    <item name="android:windowNoTitle">true</item>
</style>

人品计算器的完成

a界面塞数据,b界面取数据

Activity的数据传递

  • A activity

    Intent intent = new Intent(this, ResultActivity.class);
    intent.putExtra("name", name);//在意图对象里面携带要传递的字符串数据
    intent.putExtra("sex", rg_sex.getCheckedRadioButtonId());
    intent.putExtra("bitmap", BitmapFactory.decodeResource(getResources(), R.drawable.logo));
    startActivity(intent);
    
  • B activity

    Intent intent = getIntent();
    String name = intent.getStringExtra("name");
    Bitmap bitmap = intent.getParcelableExtra("bitmap");
    ImageView iv = (ImageView) findViewById(R.id.iv);
    iv.setImageBitmap(bitmap);
    int rb_id = intent.getIntExtra("sex", R.id.rb_male);
    
  • 传递的数据类型

    8中基本的数据类型,String,Parceable,Serializer

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值