try { // 2.把网址字符串封装成一个URL URL url = new URL(path); // 3.获取链接对象 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // 4.作参数设置,注意大写 conn.setRequestMethod("GET"); // 5.设置链接超时时间 conn.setConnectTimeout(8000); // 设置读取超时时间 conn.setReadTimeout(8000); // 发送请求,创建链接 conn.connect(); // 6. 获取返回码,判断请求返回状态 if (conn.getResponseCode() == 200) { // 请求成功 // 7.拿到服务器返回的流,里面的数据就是客户端请求的内容 InputStream is = conn.getInputStream(); // 在肯定流中数据是图片的状况下可使用Google提供的API直接生成图片,就不须要本身读取流了 //==================================================================================================================== //从流里读取数据就是在下载数据,若是网速过慢就会形成主线程阻塞(主线程阻塞在2.3能够,可是4.0+版本的Android会抛出异常) Bitmap bm = BitmapFactory.decodeStream(is); //==================================================================================================================== ImageView iv = (ImageView) findViewById(R.id.imageView1); iv.setImageBitmap(bm); } else { Toast.makeText(this, "请求失败", Toast.LENGTH_SHORT).show(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }
(应用)主线程阻塞html
规范android
问题:怎么用子线程中处理过的数据去刷新UI
MessageQueue 消息队列git
Looper 轮询器(会一直不停的检测消息队列里面是否有消息) * 消息队列没有数据,就什么都不干 * 消息队列有消息,就扔给Handler去处理程序员
Handler * handleMessage()方法用来处理消息 - 重写该方法来处理咱们的消息github
在主线程建立时会同时建立MessageQueue和Looper对象,可是Handler对象在程序员须要使用是,(程序员)自行建立。 只要消息队列有消息,handleMessage()方法就会在主线程调用编程
子线程须要刷新UI,只须要往主线程的消息队列中发送一条数据便可数组
栗子:浏览器
public class MainActivity extends Activity { // 建立消息处理器 Handler handler = new Handler() { // 重写handleMessage方法 public void handleMessage(android.os.Message msg) { switch (msg.what) { case 0: ImageView iv = (ImageView) findViewById(R.id.imageView1); iv.setImageBitmap((Bitmap) msg.obj); break; case 1: Toast.makeText(MainActivity.this, "请求失败", Toast.LENGTH_SHORT) .show(); break; } }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void click(View V) { Thread t = new Thread() { @Override public void run() { // 网址 String path = "http://192.168.15.27:8080/dd.jpg"; try { // 2.把网址字符串封装成一个URL URL url = new URL(path); // 3.获取链接对象 HttpURLConnection conn = (HttpURLConnection) url .openConnection(); // 4.作参数设置,注意大写 conn.setRequestMethod("GET"); // 5.设置链接超时时间 conn.setConnectTimeout(8000); // 设置读取超时时间 conn.setReadTimeout(8000); // 发送请求,创建链接 conn.connect(); // 6. 获取返回码,判断请求返回状态 if (conn.getResponseCode() == 200) { // 请求成功 // 7.拿到服务器返回的流,里面的数据就是客户端请求的内容 InputStream is = conn.getInputStream(); // 在肯定流中数据是图片的状况下可使用Google提供的API直接生成图片,就不须要本身读取流了 Bitmap bm = BitmapFactory.decodeStream(is); // ImageView iv = (ImageView) // findViewById(R.id.imageView1); // iv.setImageBitmap(bm); // 发送消息至主线程消息队列 Message msg = new Message(); // 利用消息对象携带数据 msg.obj = bm; // 设置状态标识(这里设置的是成功获取返回0) msg.what = 0; handler.sendMessage(msg); } else { // Message msg = new Message(); // msg.what = 0; // handler.sendMessage(msg); // 不须要携带数据时也能够发送空消息,参数what handler.sendEmptyMessage(1); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; t.start(); } }
看代码缓存
public class MainActivity extends Activity { // 建立消息处理器 Handler handler = new Handler() { // 重写handleMessage方法 public void handleMessage(android.os.Message msg) { switch (msg.what) { case 0: ImageView iv = (ImageView) findViewById(R.id.imageView1); iv.setImageBitmap((Bitmap) msg.obj); break; case 1: Toast.makeText(MainActivity.this, "请求失败", Toast.LENGTH_SHORT) .show(); break; } }; }; ………… public void click(View V) { // 网址 final String path = "http://192.168.15.27:8080/dd.jpg"; final File file = new File(getCacheDir(), getFileName(path)); // 判断文件是否已将缓存到本地 if (!file.exists()) { // 是 直接读取显示 Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath()); ImageView iv = (ImageView) findViewById(R.id.imageView1); iv.setImageBitmap(bm); } else { Thread t = new Thread() { @Override public void run() { try { // 2.把网址字符串封装成一个URL // 3.获取链接对象 // 4.作参数设置,注意大写 // 5.设置链接超时时间 // 设置读取超时时间 // 发送请求,创建链接 // 6. 获取返回码,判断请求返回状态 if (conn.getResponseCode() == 200) { // 请求成功 // 7.拿到服务器返回的流,里面的数据就是客户端请求的内容 InputStream is = conn.getInputStream(); FileOutputStream fos = new FileOutputStream(file); byte[] b = new byte[1024]; int len; while ((len = is.read(b)) != -1) { fos.write(b, 0, len); } fos.close(); //生成图片 Bitmap bm = BitmapFactory.decodeFile(file .getAbsolutePath()); // 在肯定流中数据是图片的状况下可使用Google提供的API直接生成图片,就不须要本身读取流了 // Bitmap bm = BitmapFactory.decodeStream(is); // ImageView iv = (ImageView) // 发送消息至主线程消息队列 // 利用消息对象携带数据 // 设置状态标识(这里设置的是成功获取返回0) ……………… } else { handler.sendEmptyMessage(1); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; t.start(); } } /** * 获取文件名 * * @param path * @return */ public String getFileName(String path) { int index = path.lastIndexOf("/"); return path.substring(index + 1); }
使用自定义组件时,标签名字要写包名安全
<com.loopj.android.image.SmartImageView/>
SmartImageView的使用
SmartImageView siv = (SmartImageView) findViewById(R.id.siv); siv.setImageUrl("http://192.168.1.102:8080/dd.jpg");
测试用第三方资源:android-smart-image-view-master.zip
发送GET请求
URL url = new URL(path); //获取链接对象 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //设置链接属性 conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); //创建链接,获取响应吗 if(conn.getResponseCode() == 200){ }
获取服务器返回的流,从流中把html源码读取出来
byte[] b = new byte[1024]; int len = 0; ByteArrayOutputStream bos = new ByteArrayOutputStream(); while((len = is.read(b)) != -1){ //把读到的字节先写入字节数组输出流中存起来 bos.write(b, 0, len); } //把字节数组输出流中的内容转换成字符串 //默认使用utf-8 text = new String(bos.toByteArray());
由于主线程不能执行网络下载等其余耗时的操做,而必须使用子线程去实现网络下载等操做,可是要注意这里面的线程异步问题。 如:主线程在刷新UI是调用了子线程没有处理完毕内容致使的空指针等异常
ViewHolder * 避免了重复生成大量的view对象 * 先把布局文件中的全部的组件封装到ViewHolder对象中 * ViewHolder的对象会与View一块儿被缓存起来 * 须要的时候直接xxx
解决乱码问题很是简单: 统一两遍的编码集。 android下默认编码 utf-8
客户端: 中文和特殊字符 URLEncoder.encode(); 服务器端: 默认的编码 iso-8859-1 和 本地编码(gbk)
发现 数据
�� gbk->utf-8 ??? utf-8 -> iso-8859-1 编码不存在 锟脚达拷锟斤拷 无药可救 删除了重写。
get方式提交的数据是直接拼接在url的末尾
final String path = "http://192.168.1.104/Web/servlet/CheckLogin?name=" + name + "&pass=" + pass;
发送get请求,代码和以前同样
URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setReadTimeout(5000); conn.setConnectTimeout(5000); if(conn.getResponseCode() == 200){ }
浏览器在发送请求携带数据时会对数据进行URL编码,咱们写代码时也须要为中文进行URL编码
String path = "http://192.168.1.104/Web/servlet/CheckLogin?name=" + URLEncoder.encode(name) + "&pass=" + pass;
GET方式提交数据的缺点: * 组拼http的URL的方式不安全。 * GET方式提交数据,对数据的长度是有要求的。http规范最大长度4K。
协议头中多了两个属性
Content-Length: 32,描述提交的数据的长度
//给请求头添加post多出来的两个属性 String data = "name=" + URLEncoder.encode(name) + "&pass=" + pass; conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setRequestProperty("Content-Length", data.length() + "");
设置容许打开post请求的流
conn.setDoOutput(true);
获取链接对象的输出流,往流里写要提交给服务器的数据
OutputStream os = conn.getOutputStream(); os.write(data.getBytes());
POST方式提交数据的优缺点: * 代码写起来麻烦 注意4个细节。
优势: * 安全。 * 提交数据的长度没有限制。