一、网络编程的核心步骤
(1)在清单AndroidManifest.xml文件中添加INTERNET权限。
(2)连接到网络地址的代码
第1步:创建URL
String path = "http://192.168.17.98:8080/img/news.xml"; URL url = new URL(path);
第2步:通过URL获得连接HttpURLConnection
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
第3步:通过HttpURLConnection连接设置一些请求的参数
conn.setRequestMethod("GET"); //默认请求方式就是GET,要大写。 conn.setConnectTimeout(5); //链接网络超时时间,秒作单位。
第4步:请求响应并获取服务器的响应码,判断响应码的状态,采用相应的动作。
int code = conn.getResponseCode(); /*200 代表获取服务器资源全 部成功 206 请求部分资源*/ if (code == 200) { //解析连接的输入流,获取数据,进行其它操作。 ... }
二、Android中的消息机制
在Android4.0之后,google工程师强制要求Android中的耗时操作(如上面的网络访问、拷贝
大的数据)放在子线程中运行,否则程序在运行时就会报下面这个错误:
android.os.NetworkOnMainThreadException 在主线程访问网络
然而,在子线程中往往会有更新UI的操作(如改变activity中的组件的text值),但是更新UI
的操作只能在主线程中完成,如果在子线程中有更新UI的动作,程序就会报以下错误:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original
thread that created a view hierarchy can touch its views. 只有主线程才可以更新ui
这样就形成了矛盾,那么如何解决这一矛盾呢?解决办法:有2种方式:
第1种:消息机制Handler
1)在类的成员位置上创建一个Handler对象,复写它的handleMessage(Message msg)方法。
在这个方法中获取子线程传递过来的Message,然后更新UI。
//创建助手Handler private Handler handler = new Handler(){ public void handleMessage(aMessage msg) { //获取消息的类型 switch (msg.what) { case LOADSUCESS: //代表获取数据成功 //把数据取出来 String content = (String) msg.obj; //要强转 //显示源码的内容 tv_content.setText(content); break; case LOADERROR: //代表获取数据失败 Toast.makeText(getApplicationContext(), "访问的资源不存在 ", 1).show(); break; case LOADEXCEPTION: Toast.makeText(getApplicationContext(), "服务器忙!!!", 1) .show(); break; } }; };
2)在子线程中调用Handler对象的sendMessage(Message msg)方法,将获取的数据封装到
Message中去。
//创建message对象 Message msg = Message.obtain(); //这种方式得到Message对象,可以减少 创建Message的次数。还可以new个对象 msg.what = LOADSUCESS; //标记Message的类型,int型。 msg.obj =content; //这个属性可以携带任何数据类型 //发送一条消息 告诉系统我要更新ui handleMessage方法会立刻执行 handler.sendMessage(msg);