从头学android_网络图片查看器
2016-05-30 14:32
495 查看
需求:
一个文本框,一个按钮,在文本框中输入一个图片的url,点击按钮,在按钮下方显示图像内容。layout:
manifest:
申请使用网络的权限<uses-permission android:name="android.permission.INTERNET"/>
activity
String path = editText.getText().toString(); try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setReadTimeout(8000); conn.setConnectTimeout(8000); if (conn.getResponseCode() == 200){ InputStream is = conn.getInputStream(); Bitmap bitmap = BitmapFactory.decodeStream(is); imageView.setImageBitmap(bitmap); }else{ Toast.makeText(MainActivity.this, "url错误", Toast.LENGTH_SHORT).show(); } } catch (Exception e) { e.printStackTrace(); }
结果
API14+
但是在API 14 后的android系统中,主线程不允许访问网络,以预防网络耗时所造成的阻塞报错是android.os.NetworkOnMainThreadException。
那么就用子线程来访问网络吧
editText = (EditText) findViewById(R.id.et_url); imageView = (ImageView) findViewById(R.id.imageView); final String path = editText.getText().toString(); Thread thread = new Thread(){ @Override public void run() { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setReadTimeout(8000); conn.setConnectTimeout(8000); if (conn.getResponseCode() == 200){ InputStream is = conn.getInputStream(); Bitmap bitmap = BitmapFactory.decodeStream(is); imageView.setImageBitmap(bitmap); }else{ Toast.makeText(MainActivity.this, "url错误", Toast.LENGTH_SHORT).show(); } } catch (Exception e) { e.printStackTrace(); } } }; thread.start();
结果还是不行,报错Only the original thread that created a view hierarchy can touch its views
大致意思应该就是说这个view不是你这个线程创建的,你不能更改它,那么刷新UI就只能在主线程中执行了,但是网络又不能在主线程,如果两个线程直接并行的话,无法保证给ImageView设置Bitmap时,已经拿到了服务器发送的Bitmap,这怎么办呢?
android提供了messageQueue,looper 机制来解决线程间的通信问题,消息队列中存放着消息,一旦有新的消息,轮巡器就会发现,而默认情况下,轮巡器只是发现有新消息,并不做任何事情的,如果我们希望子线程已经得到了Bitmap,发送个主线程一个消息,并附带Bitmap对象,那么就要在主线程中添加一个Handler成员,并且重写它的HandleMessage方法,在这个方法中判断消息是否是子线程发过来的得到Bitmap的消息。当子线程拿到了Bitmap时,用Handler对象发送一个消息,打上标志,附加上Bitmap对象,发送出去,那么消息队列中就会有一个新消息,轮巡器就会发现它,并调用handler的handleMessage方法执行之。真是完美,不得不膜拜谷歌大神的智慧啊!
activity(API14+)
private final static int GOTBITMAPSUCCESS = 0; private final static int WRONGURL = 1; private EditText editText; private ImageView imageView; private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case GOTBITMAPSUCCESS: Bitmap bm = (Bitmap) msg.obj; imageView.setImageBitmap(bm); break; case WRONGURL: Toast.makeText(MainActivity.this, "url错误", Toast.LENGTH_SHORT).show(); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText = (EditText) findViewById(R.id.et_url); imageView = (ImageView) findViewById(R.id.imageView); } public void showImage(View v){ final String path = editText.getText().toString(); Thread thread = new Thread(){ @Override public void run() { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setReadTimeout(8000); conn.setConnectTimeout(8000); if (conn.getResponseCode() == 200){ InputStream is = conn.getInputStream(); Bitmap bitmap = BitmapFactory.decodeStream(is); Message msg = new Message(); msg.what = GOTBITMAPSUCCESS; msg.obj = bitmap; handler.sendMessage(msg); }else{ handler.sendEmptyMessage(WRONGURL); } } catch (Exception e) { e.printStackTrace(); } } }; thread.start(); }
总结:
1.耗时操作不能放在主线程中,网络是谷歌强制要求剥离主线程的,其他的耗时操作,如读取数据等,应该自觉遵守规范,写在其他线程中去。2.子线程不能刷新UI,刷新UI必须要用主线程。
3.线程间的通讯可以使用MessageQueue-looper-Handler机制来实现。其中message可以携带对象传送数据。
相关文章推荐
- TCP协议2
- TCP协议1
- JAVA_HttpClientUtils
- 转载 HTTPS 之fiddler抓包、jmeter请求
- HTTP 消息头
- 获取网络时间
- python 批量执行脚本(服务端和客户端建立TCP连接)
- 网络 使用epoll 实现TCP服务器
- 面试题(node核心内置类库(事件,流,文件,网络等))
- 网络编程的并发问题
- Android网络基础之HttpClient与HttpURLConnection
- [Android]通过setImageURI设置网络上面的图片
- iOS网络相关零散知识总结
- Response.StatusCode的HTTP状态代码列表
- 【解决方案】cvc-complex-type.2.4.a: Invalid content was found starting with element 'init-param'. One of '{"http://java.sun.com/xml/ns/javaee":run-as, "http://java.sun.com/xml/ns/javaee":security-role-r
- 用Java后台+Android_写一个简单的HttpConnection
- JAVA_网络编程
- 部署 Bonobo Git Server 时,出现 HTTP 错误 500.19 解决办法
- 网络文件系统
- [整理]通过http1.1 GET, POST, PUT, PATCH, DELETE, HEAD, TRACE理解真正的RESTFUL