Android学习五 网络编程与handler消息机制
来源:互联网 发布:淘宝投诉卖家后没用啊 编辑:程序博客网 时间:2024/05/22 11:38
Android中许多应用需要从网络上获取内容,而如何从网络上获取内容,这就需要用到网络编程的知识。下面是Android中关于网络编程的一些知识。
一、使用httpURLConnection对象访问网络
使用UrlConnection请求一个url地址获取内容的一般步骤如下:
//1.创建一个Url对象
URL url = new URL(url_str);
//2.获取一个UrlConnection对象
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
//3.为UrlConnection对象设置一些请求的参数,请求方式,连接的超时时间
connection.setRequestMethod("GET");//设置请求方式
connection.setConnectTimeout(1000*10);//设置超时时间
//4.在获取url请求的数据前需要判断响应码,200 :成功,206:访问部分数据成功 300:跳转或重定向 400:错误 500:服务器异常
int code = connection.getResponseCode();
//5.获取有效数据,并将获取的流数据解析成String
InputStream inputStream = connection.getInputStream();
String result = StreamUtils.streamToString(inputStream);
注意访问网络需要设置android.permission.INTERNET 这个权限。
如果直接在主线程中做网络请求的话,可能会ANR:application not response 应用无响应的错误,这是因为Android中的耗时操作(请求网络,大文件的拷贝,数据库的操作等)需要在子线程中去做,但是在子线程中不能够更新控件(如Toast的展示及其他界面的修改操作)。这是可能就会产生问题,当即需要请求网络有需要更新UI时该怎么办呢?
这是后就需要handler了。
二、handler的使用
handler可以在子线程和主线程之间传递消息,当子线程中需要更新UI时,只需要把要更新的内容用handler传递到主线程中,在主线程中更新即可。下面来看一下handler的用法。
1.主线程中创建一个Handler
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
};
};
2.重写handler的handlermessage方法
3.子线程中创建一个Message对象,将获取的数据绑定给msg
Message msg = new Message();
//另一种方式:Message msg = Messge.obtain;
msg.obj = result;
4.主线程中的handler对象在子线程中将message发送给主线程
handler.sendMessage(msg);
5.主线程中handlermessage方法接受子线程发来的数据,就可以做更新UI的操作。
下面来看一段示例代码:
private EditText et_url; private TextView tv_source; private Context mContext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContext = this; //一、获取控件 et_url = (EditText) findViewById(R.id.et_url); Button bt_looksource = (Button) findViewById(R.id.bt_looksource); tv_source = (TextView) findViewById(R.id.tv_source); //二、绑定点击事件 bt_looksource.setOnClickListener(this); System.out.println("oncreate方法线程:"+Thread.currentThread().getName()); } //使用handler在子线程和主线程之间传递消息的步骤 //a.在主线程中创建一个handler对象 private Handler handler = new Handler(){ //b重写handler对象中的handlerMessage方法,用来接收子线程中发来的消息 @Override public void handleMessage(Message msg) { //e.接收子线程发来的消息,处理消息 String result = (String)msg.obj; System.out.println("获取到信息"); //五、更新UI tv_source.setText(result); } }; @Override public void onClick(View view) { //ctrl+alt+t快速添加try catch块 try { //三、获取输入的url地址 final String url_str = et_url.getText().toString().trim(); if(TextUtils.isEmpty(url_str)){ //??? Toast.makeText(mContext,"url不能为空",Toast.LENGTH_SHORT).show(); return ; } System.out.println("onclick方法线程:"+Thread.currentThread().getName()); //四、创建一个子线程做网络请求 new Thread(new Runnable() { @Override public void run() { try { System.out.println("oclick方法runnable线程:"+Thread.currentThread().getName()); //使用UrlConnection请求一个url地址获取内容 //1.根据url地址创建一个URL对象 URL url = new URL(url_str); //2.获取一个URLConnection对象 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(1000*10); System.out.println("第一次请求的请求码"+connection.getResponseCode()); //3.获取头部信息,获取到重定向后的地址(为了解决返回码为302的问题) String location = connection.getHeaderField("Location"); System.out.println("location "+location+""); //4.为URLConnection设置请求参数(请求方式,连接的超时时间等) url = new URL(location); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(1000*10); //4.判断响应码 int code = connection.getResponseCode(); System.out.println(code); if(code == 200){ //5.获取有效数据,并将数据解析为字符串 InputStream inputStream = connection.getInputStream(); String result = StreamUtils.streamToString(inputStream); //c.子线程中创建一个Message对象,用于将子线程中的数传递给主线程 Message message = new Message(); message.obj = result; //d.使用handler将数据从子线程传递到主线程 handler.sendMessage(message); }else{ System.out.println("请求url失败"); } } catch (Exception e) { e.printStackTrace(); } } }).start(); } catch (Exception e) { e.printStackTrace(); } }
public class StreamUtils { public static String streamToString(InputStream in){ String result = ""; try { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int length = 0; while((length = in.read(buffer)) != -1){ out.write(buffer,0,length); out.flush(); } result = out.toString(); out.close(); } catch (IOException e) { e.printStackTrace(); } return result; }}在子线程中更新UI的其他集中方法:
1.使用activity的runOnUiThread方法更新ui,无论当前线程是否是主线程,都将在主线程执行。注意runOnUiThread不能在静态类中使用
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_simple.setText("我被更新了");
}
});
2.使用handler直接post到主线程,handler需要在主线程创建
//延迟多少毫米执行runnable。
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
tv_simple.setText("我被更新了");
}
}, 1000*5);
还有需要注意的是不能在子线程中更新UI并不是绝对的。以下集中情形可以在子线程中更新UI:SurfaceView :多媒体视频播放 ,可以在子线程中更新UI; Progress(进度)相关的控件:也是可以在子线程中更新Ui;审计机制:activity完全显示的时候审计机制才会去检测子线程有没有更新Ui。
三、get和post请求
在请求网络时需要设置请求方式,常用的请求方式有两种post和get。get的请求内容是跟在URL地址后面(不安全且大小有限制但是简单),post的请求内容是放在请求体当中(大小无限制,安全,但是繁琐)。使用post请求相比get请求还需要设置一下内容:
请求头的设置(不是必需的)
openConnection.setRequestProperty("Content-Length", body.length()+"");
openConnection.setRequestProperty("Cache-Control", "max-age=0");
openConnection.setRequestProperty("Origin", "http://192.168.13.83:8080");
请求内容的设置(必需)
//设置UrlConnection可以写请求的内容
openConnection.setDoOutput(true);
//获取一个outputstream,并将内容写入该流
openConnection.getOutputStream().write(body.getBytes());
使用post请求方式时还要注意编码要一致,否则可能产生乱码。可以使用URLEncode对数据进行编码。
四、用httpClient做网络请求
直接上代码,get方式:
try{String path = "http://192.168.13.83:8080/itheima74/servlet/LoginServlet?username="+URLEncoder.encode(username,"utf-8")+"&pwd="+URLEncoder.encode(password,"utf-8");//1.创建一个httpClient对象HttpClient httpclient = new DefaultHttpClient();//2.设置请求的方式HttpGet httpget = new HttpGet(path);//3.执行一个http请求HttpResponse response = httpclient.execute(httpget);//4.获取请求的状态码,StatusLine statusLine = response.getStatusLine();int code = statusLine.getStatusCode();//5.判断状态码后获取内容if(code == 200){HttpEntity entity = response.getEntity();//获取实体内容,中封装的有http请求返回的流信息InputStream inputStream = entity.getContent();//将流信息转换成字符串String result = StreamUtils.streamToString(inputStream);Message msg = Message.obtain();msg.what = 1;msg.obj = result;handler.sendMessage(msg);}}catch (Exception e) {e.printStackTrace();}post方式:
String path = "http://192.168.13.83:8080/itheima74/servlet/LoginServlet";AsyncHttpClient asyncHttpClient = new AsyncHttpClient();RequestParams params = new RequestParams();params.put("username", username);params.put("pwd", password);//url: parmas:请求时携带的参数信息 responseHandler:是一个匿名内部类接受成功过失败asyncHttpClient.post(path, params, new AsyncHttpResponseHandler() {@Overridepublic void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {//statusCode:状态码 headers:头信息 responseBody:返回的内容,返回的实体//判断状态码if(statusCode == 200){//获取结果try {String result = new String(responseBody,"utf-8");Toast.makeText(context, result, 0).show();} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}@Overridepublic void onFailure(int statusCode, Header[] headers,byte[] responseBody, Throwable error) {}});
- Android学习五 网络编程与handler消息机制
- 【Android学习】消息机制Handler
- 网络编程之Handler消息机制
- android学习--消息机制Handler Loop MesssageQueue
- android学习13#--Handler消息传递机制
- 【Android自助餐】Handler消息机制完全解析(五)鸟瞰与总结
- Android Handler消息机制
- android handler消息机制
- android handler消息机制
- Android Handler消息机制
- android handler消息机制
- android handler消息机制
- Android:Handler消息机制
- Android Handler 消息机制
- Android Handler消息机制
- android消息机制handler
- Android 消息机制--handler
- android消息机制-handler
- 数组中的最长连续序列---dp实现
- Hibernate架构
- 勒索病毒来袭!及时备份数据吧!
- 深度学习经验总结
- myeclipse 工具点击close all 项目不再图形化界面,怎么调出来
- Android学习五 网络编程与handler消息机制
- u-boot环境变量与内核MTD分区关系[转载]
- [脑科学]-这才是心理学
- Linux 下 Java JDK 安装流程
- JAVA基础学习---- 封装
- 对象的一些模糊
- Windows系统打开Linux下Ext格式磁盘方式
- PHP 多线程
- redis 一(nosql介绍)