读书人

Android 兑现联网(三)在线程中联

发布时间: 2012-07-26 12:01:08 作者: rapoo

Android 实现联网(三)——在线程中联网

在前面的关于Java?I/O的学习中,有一个我们需要牢记的是:对数据流的操作都是阻塞的,在一般情况下,我们是不需要考虑这个问题的,但是在Android?实现联网的时候,我们必须考虑到这个问题。比如:从网络上下载一张图片:

Java代码?
  1. public?Bitmap returnBitmap(String url)
  2. {
  3. URL myFileUrl =?null;
  4. Bitmap bitmap =?null;
  5. try{
  6. myFileUrl =?new?URL(url);
  7. }catch(MalformedURLException e){
  8. e.printStackTrace();
  9. return?null;
  10. };
  11. try{
  12. HttpURLConnection conn = (HttpURLConnection)myFileUrl.openConnection();
  13. conn.setDoInput(true);
  14. conn.connect();
  15. InputStream is = conn.getInputStream();
  16. bitmap = BitmapFactroy.decodeStream(is);
  17. is.close();
  18. }catch(IOException e){
  19. e.printStackTrace();
  20. }
  21. return?bitmap;
  22. }


由于网络连接需要很长的时间,需要3-5秒,甚至更长的时间才能返回页面的内容。如果此连接动作直接在主线程,也就是UI线程中处理,会发生什么情况呢? 整个程序处于等待状态,界面似乎是“死”掉了。为了解决这个问题,必须把这个任务放置到单独线程中运行,避免阻塞UI线程,这样就不会对主线程有任何影 响。举个例子如下:

Java代码?
  1. private?void?connect(String strURL){
  2. new?Thread() {
  3. public?void?run() {
  4. try?{
  5. HttpClient client =?new?DefaultHttpClient();
  6. // params[0]代表连接的url
  7. HttpGet get =?new?HttpGet(url.getText().toString());
  8. HttpResponse response = client.execute(get);
  9. HttpEntity entity = response.getEntity();
  10. long?length = entity.getContentLength();
  11. InputStream is = entity.getContent();
  12. String s =?null;
  13. if?(is !=?null) {
  14. ByteArrayOutputStream baos =?new?ByteArrayOutputStream();
  15. byte[] buf =?new?byte[128];
  16. int?ch = -1;
  17. int?count =?0;
  18. while?((ch = is.read(buf)) != -1) {
  19. baos.write(buf,?0, ch);
  20. count += ch;
  21. }
  22. s =?new?String(baos.toByteArray());
  23. Log.V(“moandroid sample”,s);
  24. }
  25. }?catch?(Exception e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. }.start();
  30. }

?

使用Handler更新界面

如何将下载的信息显示在界面上了,比如说下载的进度。Android?SDK平台只允许在主线程中调用相关View的方法来更新界面。如果返回结果在新线程中获得,那么必须借助Handler来更新界面。为此,在界面 Activity中创建一个Handler对象,并在handleMessage()中更新UI。

Java代码?
  1. //Task在另外的线程执行,不能直接在Task中更新UI,因此创建了Handler
  2. private?Handler handler =?new?Handler() {
  3. @Override
  4. public?void?handleMessage(Message msg) {
  5. String m = (String) msg.obj;
  6. message.setText(m);
  7. }
  8. };


只需要将上面的


替换为:

Java代码?
  1. s =?new?String(baos.toByteArray());
  2. Message mg = Message.obtain();
  3. mg.obj = s;
  4. handler.sendMessage(mg);

?

AsyncTask

看上去修改后的connect()方法已经可用了,但是这种匿名程的方式是存在缺陷的:

读书人网 >Android

热点推荐