- 浏览: 159582 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
hmxingkong:
Run Configurations -> Target ...
INSTALL_FAILED_INSUFFICIENT_STORAGE调试错误的解决 -
samkifeng:
...
MO,MT,Linkid的关系 -
wwwjiandan:
“Eclipse中在项目Target的Options中添加。” ...
INSTALL_FAILED_INSUFFICIENT_STORAGE调试错误的解决 -
cskymq:
怎么获取版本号啊?
【转】获取未安装的APK信息 -
c1007857613:
默认情况下是没有锯齿效果嘛?为什么我没有设置锯齿画出来的直 ...
Android Canvas绘图抗锯齿解决方法
在前面的关于Java I/O的学习中,有一个我们需要牢记的是:对数据流的操作都是阻塞的,在一般情况下,我们是不需要考虑这个问题的,但是在Android 实现联网的时候,我们必须考虑到这个问题。比如:从网络上下载一张图片:
public Bitmap returnBitmap(String url) { URL myFileUrl = null; Bitmap bitmap = null; try{ myFileUrl = new URL(url); }catch(MalformedURLException e){ e.printStackTrace(); return null; }; try{ HttpURLConnection conn = (HttpURLConnection)myFileUrl.openConnection(); conn.setDoInput(true); conn.connect(); InputStream is = conn.getInputStream(); bitmap = BitmapFactroy.decodeStream(is); is.close(); }catch(IOException e){ e.printStackTrace(); } return bitmap; }
由于网络连接需要很长的时间,需要3-5秒,甚至更长的时间才能返回页面的内容。如果此连接动作直接在主线程,也就是UI线程中处理,会发生什么情况呢?
整个程序处于等待状态,界面似乎是“死”掉了。为了解决这个问题,必须把这个任务放置到单独线程中运行,避免阻塞UI线程,这样就不会对主线程有任何影
响。举个例子如下:
private void connect(String strURL){ new Thread() { public void run() { try { HttpClient client = new DefaultHttpClient(); // params[0]代表连接的url HttpGet get = new HttpGet(url.getText().toString()); HttpResponse response = client.execute(get); HttpEntity entity = response.getEntity(); long length = entity.getContentLength(); InputStream is = entity.getContent(); String s = null; if (is != null) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buf = new byte[128]; int ch = -1; int count = 0; while ((ch = is.read(buf)) != -1) { baos.write(buf, 0, ch); count += ch; } s = new String(baos.toByteArray()); Log.V(“moandroid sample”,s); } } catch (Exception e) { e.printStackTrace(); } } }.start(); }
使用Handler更新界面
如何将下载的信息显示在界面上了,比如说下载的进度。Android SDK平台只允许在主线程中调用相关View的方法来更新界面。如果返回结果在新线程中获得,那么必须借助Handler来更新界面。为此,在界面 Activity中创建一个Handler对象,并在handleMessage()中更新UI。
//Task在另外的线程执行,不能直接在Task中更新UI,因此创建了Handler private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { String m = (String) msg.obj; message.setText(m); } };
只需要将上面的
Log.V(“moandroid sample”,s);
替换为:
s = new String(baos.toByteArray()); Message mg = Message.obtain(); mg.obj = s; handler.sendMessage(mg);
AsyncTask
看上去修改后的connect()方法已经可用了,但是这种匿名程的方式是存在缺陷的:
- 线程的开销较大,如果每个任务都要创建一个线程,那么应用程 序的效率要低很多;
- 线程无法管理,匿名线程创建并启动后就不受程序的控制了,如果有很多个请求发送,那么就会启动非常多的线程,系统将不堪重负。
- 另外,前面已经看到,在新线程中更新UI还必须要引入handler,这让代码看上去非常臃肿。
为了解决这一问题,Android在1.5版本引入了AsyncTask。AsyncTask的特点是任务在主线程之外运行,而回调方法是在主线程
中执行,这就有效地避免了使用Handler带来的麻烦。阅读AsyncTask的源码可知,AsyncTask是使用
java.util.concurrent
框架来管理线程以及任务的执行的,concurrent框架是一个非常成熟,高效的框架,经过了严格的测试。这说明AsyncTask的设计很好的解决了
匿名线程存在的问题。
AsyncTask是抽象类,其结构图如下图所示:
AsyncTask定义了三种泛型类型 Params,Progress和Result。
- Params 启动任务执行的输入参数,比如HTTP请求的URL。
- Progress 后台任务执行的百分比。
- Result 后台执行任务最终返回的结果,比如String。
子类必须实现抽象方法doInBackground(Params… p)
,在此方法中实现任务的执行工作,比如连接网络获取数据等。通常还应该实现onPostExecute(Result
r)方法,因为应用程序关心的结果在此方法中返回。需要注意的是AsyncTask一定要在主线程中创建实例。
AsyncTask的执行分为四个步骤,每一步都对应一个回调方法,需要注意的是这些方法不应该由应用程序调用,开发者需要做的就是实现这些方法。在任务
的执行过程中,这些方法被自动调用,运行过程,如下图所示:
- onPreExecute() 当任务执行之前开始调用此方法,可以在这里显示进度对话框。
- doInBackground(Params…) 此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的 进度。
- onProgressUpdate(Progress…) 此方法在主线程执行,用于显示任务执行的进度。
- onPostExecute(Result) 此方法在主线程执行,任务执行的结果作为此方法的参数返回。
举个简单的例子如下:
// 设置三种类型参数分别为String,Integer,String class PageTask extends AsyncTask { // 可变长的输入参数,与AsyncTask.exucute()对应 @Override protected String doInBackground(String… params) { try { HttpClient client = new DefaultHttpClient(); // params[0]代表连接的url HttpGet get = new HttpGet(params[0]); HttpResponse response = client.execute(get); HttpEntity entity = response.getEntity(); long length = entity.getContentLength(); InputStream is = entity.getContent(); String s = null; if (is != null) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buf = new byte[128]; int ch = -1; int count = 0; while ((ch = is.read(buf)) != -1) { baos.write(buf, 0, ch); count += ch; if (length > 0) { // 如果知道响应的长度,调用publishProgress()更新进度 publishProgress((int) ((count / (float) length) * 100)); } // 为了在模拟器中清楚地看到进度,让线程休眠100ms Thread.sleep(100); } s = new String(baos.toByteArray()); } // 返回结果 return s; } catch (Exception e) { e.printStackTrace(); } return null; } @Override protected void onCancelled() { super.onCancelled(); } @Override protected void onPostExecute(String result) { // 返回HTML页面的内容 message.setText(result); } @Override protected void onPreExecute() { // 任务启动,可以在这里显示一个对话框,这里简单处理 message.setText(R.string.task_started); } @Override protected void onProgressUpdate(Integer… values) { // 更新进度 message.setText(values[0]); } } 执行PageTask非常简单,只需要调用如下代码。 PageTask task = new PageTask(); task.execute(url.getText().toString());
总结说明
Handler在前面我们已经学习过,今天突然看到AsyncTask,以及学习其他人的博客基础上,做出了上面的总结,感觉自己收获很多,在这里 与大家分享。
发表评论
-
平滑摇杆的实现
2010-08-09 14:05 1366很久不写关于游戏逻辑的文章了,略显生疏了,最近公司 ... -
bitmap 设置图片尺寸,避免 内存溢出 OutOfMemoryError的优化方法
2010-07-15 11:20 12898★android 中用bitmap 时很 ... -
EditText仅允许特定类型数据输入
2010-06-11 13:32 2960很多网友可能在开发Android时发现EditText有时候需 ... -
Android程序完全退出的三种方法
2010-06-11 13:22 9973很多网友可能发现自 ... -
androidmanifest.xml高级属性解析
2010-06-09 00:04 1256Android工程的的主配置文件androidmanifest ... -
自定义Android应用的访问权限
2010-06-09 00:00 2036由于Android部分设计原理较为开放,可能通过Intent或 ... -
【转】用代码安装APK程序
2010-06-08 23:21 1239安装APK程序可以通过连接PC端安装,还有通过网络下载安装。 ... -
【转】实现Activity不压入Activity栈
2010-06-08 23:18 1012我们要实现在Activity栈里只存在一个相同的Activit ... -
【转】SDK1.5r3以后写入SDCARD记得加权限
2010-06-08 23:17 1149这两天把程序移到SDK1.6上编译,遇到对SDCARD写入的问 ... -
【转】显示和隐藏软键盘
2010-06-08 23:15 1191InputMethodManager imm = (Input ... -
【转】获取未安装的APK信息
2010-06-08 23:10 2717在前面的文章发过一篇《获取已安装程序的名字、包名、版本和图标》 ... -
【转】获取已安装程序的名字、包名、版本和图标
2010-06-08 23:08 1522class PInfo { private ... -
【转】释放内存中的图片资源
2010-06-08 23:00 1182最近做的项目用到很多图片,经常出现内存溢出。 Ando ... -
设置桌面快捷方式
2010-06-07 00:24 1376如何在程序中设置桌面快捷方式(home screen sho ... -
Android2.2中的APK安装参数installLocation
2010-05-31 10:49 1479在Android 2.2中新的特性可以支持类似APP2S ... -
我的命令工厂(一) —— 泛型
2010-05-31 10:39 993泛型开发已经是java编程中老生常谈的问题了,这里 ... -
【转】Android 实现联网(四)——TCP/UDP
2010-05-31 10:19 1982在java.net漫游 篇幅 中,我们详细介绍了与网络相关 ... -
【转】Android 实现联网(二)——java.net漫游
2010-05-31 10:17 2009相比较C++,JAVA在网络编 ... -
【转】Android 实现联网(一)——package说明
2010-05-31 10:09 1775今天我们将深入介绍了A ... -
彻底kill当前activity的processor
2010-05-27 14:17 1060在Activity中的onDestroy中完成以下代码 ...
相关推荐
使用Android实现联网 使用Android实现联网
车联网社交——车联网发展的新起点.pdf
学习使用AndroidStudio开发App
车联网:惠州后装市场的车联网命题——惠州后装企业的车联网产业布局正在聚集.pdf
“车联网”——未来城市个人交通的美好愿景.pdf
打造未来车联网生活——沃尔沃SENSUS.pdf
家庭联网必备——智能无线路由器选购.pdf
车联网前程远大——2019年车联网产业发展报告.pdf
安卓Android源码——联网分类菜谱项目.zip
全面布局车联网生态——本刊专访四维图新总裁程鹏.pdf
车联网大会——千亿资金聚焦“第四终端”.pdf
热点追踪——车联网——车联网新技术与应用.pdf
汽车行业:车联网研究——智能化凸显,产业迎来爆发期
汽车行业:车联网研究——智能化凸显,产业迎来爆发期.pdf
Android开发从入门到精通6-使用Android实现联网.doc
用车载应用思维做标准车联网服务——本刊专访赛格导航导航事业部总经理洪军.pdf
赛格导航:服务、开放引领车联网潮流——本刊专访赛格导航导航事业部总经理洪军.pdf
数联网——大数据如何互联epub格式
此pdf是教学Android中联网的教程
物联网——车联网 物联网——车联网全文共26页,当前为第1页。 物联网的应用非常广泛,归纳起来目前主要有四个领域值得特别关注: 环境监控 物品溯源 智能电网 智能交通。 物联网——车联网全文共26页,当前为第2页...