android网络编程
- 一般请求数据用HTTP协议
- 即时通讯软件用XNPP协议(陌陌),腾讯私有自建的协议
- RTSP协议:网络流媒体(在线视频)
网络请求
主线程阻塞
- UI停止刷新,应用无法响应用户操作
- 耗时操作不应该在主线程进行
- ANR
- application not responding
- 应用无响应异常
- 主线程阻塞时间过长,就会抛出ANR
- 主线程又称UI线程,因为只有在主线程中,才能刷新UI
消息队列机制
- 主线程创建时,系统会同时创建消息队列对象(message queue)和消息轮询器对象(Looper)
- message queue:消息队列,存储消息的
- Looper:消息轮询器:不停的检测消息队列中是否有消息(Message)
- Handler:消息处理器;轮询器会把消息对象传给消息处理器(Handler);调用handleMessage()处理消息的方法(handleMessage()运行在主线程中,所以可以刷新UI)(但是主线程中没有被创建,什么时候使用,自己创建就好)
- 总结:只要消息队列有消息,handleMessage方法就会调用
- 子线程如果需要刷新UI,只需要往消息队列中发一条消息,触发handleMessage即可
- 子线程使用处理器对象的sendMessage方法发送消息
- 子线程使用Handler对象来发送消息,消息会被发送至主线程的消息队列
- 消息对象也可以携带数据:Message msg =new Message();但是一般在开发中最好不要直接new一个对象,而是:Message msg =handler.obtainMessage();//这样做比较节省内存。
- msg.what = 0;//处理时根据这个值判断是成功消息还是失败消息。
- 如果是多图的软件,需要把图片缓存到本地,避免重复下载!之后如何缓存存在就从缓存中读取图片;如果不存在就从网络上下载(沾代码就行)
普遍的需求,网上都有成熟的第三方的API
谷歌代码管理平台(需翻墙,用的少,资源不多)
- Http://code.google.com/
- 很多代码去下载借鉴和使用
- 很多世界各地的软件
- 还有其他代码管理平台;
github首页(国内用的多一点)
- Http://github.com/
- 比如搜索:smart-image-view;图片查看器(直接用);
- 比如:asyn-http;异步HttoClient开源框架
- afinal控件:内置四大控件–>xUtils:断点续传HttpUtils;
使用自定义控件
- 写名的时候加全路径(com.xxx.SmartImageView)
- 使用安卓自带控件只需要写控件名就行(ImageView)
新闻简易客户端(知识点补充)
- 显示单行: android:singleLine=”true”
- 只显示两行:android:lines=”2”
使用HttpClient框架做数据提交
- 由于使用post、get方式比较麻烦,这时候就出现了封装好的框架HttpClient
- 使用HttpClient框架提交数据(google已经封装至android中了)
一个接口如果方法过多的话,就不会直接new,一般会提供一个Basic或者Default之类的来使用这个借口!(Ctrl+T)
//使用HttpClient框架做get方式提交,拼接一下字符串 String path = "http://asdasdasd?name="+URLEncoder.encode(name)+"&password="+password; //1、创建HttpClient对象 HttpClient client = new DefaultHttpClient(); //2、创建HttpGet对象,构造方法的参数就是网址 HttpGet get = new HttpGet(path); try{ //3、使用客户端对象把get请求对象发送出去 HttpResponse hr = client.excute(get); //4、拿到响应头中的状态行(响应码在状态行内) if(hr.getStatusLine().getStatusCode()==200){ //拿到流(流在响应头的实体内) //拿到响应头的实体 HttpEntity he = hr.getEntity(); //拿到实体中的内容,其实就是服务器返回的输入流 InputStream is = he.getContent(); } }catch(Exception e){ e.printStackTrace(); }
*
//使用HttpClient框架做POST方式提交,POST是把数据放在流内传递
EditText et_name = (EditText)findViewById(R.id.et_name);
EditText et_password = (EditText)findViewById(R.id.et_password);
String name = et_name.getText().toString();
String password = et_password.getText().toString();
String path = "";
//1、创建客户端对象
HttpClient hc = new DefaultHttpClient();
//2、创建POST请求对象
HttpPost hp = new HttpPost(path);
//设置POST请求对象的实体,其实就把要提交的数据封装至post请求的输出流中
BasicNameValuePair bnvp = new BasicNameValuePair("name",name);
BasicNameValuePair bnvp2 = new BasicNameValuePair("password",password);
List<BasicNameValuePair> parameters = ArrayList<BasicNameValuePair>();
//把 BasicNameValuePair放到集合中
list.add(bnvp);
list.add(bnvp2);
try{
//要提交的数据都已经在集合中了,把集合传给实体对象
UrlEncodeFormEntity entity = new UrlEncodeFormEntity(parameters,"utf-8");
//3、使用客户端发送POST请求
hp.send(entity);
//响应
HttpResponse hr = hc.execute(hp);
if(hr.getStatusLines().getStatusCode()==200){
InputStream is = hr.getEntity().getContent();
}
}catch(Exception e){e.printStackTrace();}
多线程断点续传
- 多线程比单线程更快原理:因为在向服务器请求资源的时候,服务器分配给每个线程的带宽是一样的,多线程就可以占用多个带宽,抢得更多的资源,从而提高效率!
- 多线程分配起始位置公式:
- 写入硬盘缓冲区的文件断电就没了,所以使用断点续传,要直接写入底层存储设备。
RandomAccessFile生成临时文件流
*设置本次http请求所请求的数据的区间(开始到结束) conn.setRequestProPerty("Range","bytes="+startIndex+"-"+endIndex); //请求部分数据的正确码为206 if(conn.getResponseCode==206){} //把文件的写入位置移动到start位置 raf.seek(startIndex);