Android07
为什么多线程可以提高下载速度
对于同一个资源,开多个口子平均去下载,肯定是比一个口子从头下到尾块
多线程下载的步骤
- 客服端创建空白文件和服务器文件大小一样
- 开启n个线程,资源要等分
- 服务器下载完毕,多线程下载完毕
如何划分服务器的资源给不同的线程
每个线程需要下载的区块 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();
}
}
多线程断点下载的移植
SD卡的路径
RandomAccessFile raf = new RandomAccessFile(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+getFileName(path), "rw");
SD卡的权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
子线程访问网络
new Thread(){
public void run() {
访问网络的套路
}
}.start(); }
开源项目实现多线程断点下载
导包
xUtils.jar代码实现
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(); } });
权限
//网络权限和SDcard写权限 <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
多界面应用程序的开发
activity的创建步骤
- 写一个类继承Activity.重写onCreate方法
- 在清单文件的application节点下面配置 android:name
ActivityNotFoundException - 创建一个布局文件 res/layout
- onCreate设置布局 setContentView(R.layout.);
activity的跳转
- 创建意图的对象 Intent intent = new Intent();
- 设置意图的跳转方向 intent.setClass(context,OtherActivity.class);
- 开启意图 startActivity(intent);
- 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