Android基础 第五天

GET方式提交数据

HttpUrlConnection提交数据到服务器

get提交提交数据到服务器 (数据拼接到到哪里?)

拼接到URL后面用”?”问号起步然后多个数据之间用 & 符号衔接
http://www.ithcl.com?qqq=xxx&pwd=yyyy
post提交数据提交到服务器

(数据是写到哪里的?用post提交的时候需要设置两个头信息,还要设置开启输出流,最后通过conn.getOutputStream拿到一个输出流,向服务器写数据)
//两个头信息
conn.setRequestProperty(“Content-Type”, “application/x-www-form-urlencoded”);
conn.setRequestProperty(“Content-Length”, String.valueOf(data.length()));

conn.setDoOutput(true);//不要忘记这行代码
conn.getOutputStream().write(data.getBytes());//向服务器写数据
这两个写完之后,要总结 两者的差异!! 比如: post请求要多设置几个头信息 , 写数据的之前要注意什么细节! 数据的提交方式区别

HttpClient方式 GET 传递数据,(Android6.0之后被废弃掉了)

httpClient的这种方式更加面向对象,代码更好理解

用这种方式要需要设置两个头信息吗? 不需要,应为HttpClient把这些细节都给封装起来了,不用需关心其中的细节

String path = “http://192.168.1.103:8080/web/LoginServlet?qq=“+URLEncoder.encode(qq, “utf-8”)+”&pwd=”+URLEncoder.encode(pwd, “utf-8”);
//1.打开浏览器 simple base default
HttpClient client = new DefaultHttpClient();
//2.输入地址或者数据
HttpGet httpGet = new HttpGet(path);
//3.敲回车
HttpResponse response = client.execute(httpGet);

//获取状态码
int code = response.getStatusLine().getStatusCode();
if(code == 200){
//拿到服务器返回的输入流,
InputStream is = response.getEntity().getContent();
//开始读取数据,后面和HttpUrlConnection 就一样了
String result = StreamTools.readStream(is);
……发消息,更新UI线程
HttpClient方式 POST 传数据

String path = “http://192.168.1.103:8080/web/LoginServlet“;
//1.打开浏览器
HttpClient client = new DefaultHttpClient();

//2.输入地址或者数据
HttpPost httpPost = new HttpPost(path);
HttpGet httpGet = new HttpGet(path);
//3.准备数据
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
parameters.add(new BasicNameValuePair("qq", qq));//map
parameters.add(new BasicNameValuePair("pwd", pwd));
//4.把数据加入到httpPost中
httpPost.setEntity(new UrlEncodedFormEntity(parameters, "utf-8"));

//3.敲回车
HttpResponse response = client.execute(httpPost);
//获取状态码
int code = response.getStatusLine().getStatusCode();
if(code == 200){
    InputStream is = response.getEntity().getContent();
    String result = StreamTools.readStream(is);
    ....

多线程断点下载

在写代码之前必须先看着图片 先把思路整理清楚,然后再开始写代码!

1,请求服务器得到即将下载文件的大小(发送一次get请求),然后在本地用RandomAccessFile创建一个大小和服务器文件大小一样的文件!
int length = conn.getContentLength();
RandomAccessFile raf = new RandomAccessFile(getFileName(path), “rw”);
raf.setLength(length); //关键的代码,设置文件的大小

2,计算每个线程下载的起始位置和结束位置(有个公式,看今天的资料图),最后一个线程比较特殊,它的结束位置是totalLength -1 !!!
int blocksize = length / threadCount;
for (int threadId = 0; threadId < threadCount; threadId++) {
int startIndex = threadId * blocksize;
int endIndex = (threadId + 1) * blocksize - 1;
if (threadId == (threadCount - 1)) {
endIndex = length - 1;
}
new DownloadThread(threadId, startIndex, endIndex).start();
}
3,开启每个线程去下载文件的某一部分(怎么告诉服务器只下载一部分?Range),同时写文件的时候要记得调用RandomAccessFile的seek方法,调整写入的位置!!
conn.setRequestProperty(“Range”, “bytes=”+startIndex+”-“+endIndex);
raf.seek(xxx)
4,断点下载的本质是,每次下载一点内容,就将当前的进度保存到文件里面去(RandomAccessFile的模式rwd,”d” 代表着 数据是立刻被存储到底层硬盘设备里面)
while((len = is.read(buffer))!=-1){
//把每个线程下载的数据放在自己的空间里面.
System.out.println(“线程:”+threadId+”正在下载:”+new String(buffer));
raf.write(buffer,0, len);
//len 代表着每次写入文件数据的大小,也就是代表着进度!
currentPosition+=len;

    File file = new File(threadId+".position");
    RandomAccessFile fos = new RandomAccessFile(file,"rwd");
    //System.out.println("线程:"+threadId+"写到了"+currentPosition);
    fos.write(String.valueOf(currentPosition).getBytes());
    fos.close();//fileoutstream数据是不一定被写入到底层设备里面的,有可能是存储在缓存里面.
    //raf 的 rwd模式,数据是立刻被存储到底层硬盘设备里面.
}

下次再次开启的时候,判断一下文件内容是否存在,如果有,代表着要从原来的位置开始
将里面的内容读取出来,然后——很重要——>重新设置告诉服务器下载的范围(Range)和调用RandomAccessFile的seek方法,调整写入的位置!
//检查当前线程是否已经下载过一部分的数据了
File info = new File(threadId+”.position”);
RandomAccessFile raf = new RandomAccessFile(getFileName(path), “rw”);
if(info.exists()&&info.length()>0){
FileInputStream fis = new FileInputStream(info);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));

currentPosition = Integer.valueOf(br.readLine());

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);//每个线程写文件的开始位置都是不一样的.
}

5,当所有的线程都下载完毕之后,要删除临时保存的文件,以免出现bug。
(用一个变量当作计数器,当多线程改变一个变量的时候,要记住加上synchronized关键字同步起来,以免发生数据的错乱)
synchronized (MultiDownloader.class) {
runningThreadCount–;
if(runningThreadCount<=0){
for(int i=0;i

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值