第八章 网络的时代—网络开发(3)

8.4耗时操作的通用方式—多线程与异步处理

Android通过一个主线程对用户界面进行更新,这个线程是UI线程。如果程序不使用任何并发构建、Android的所有代码都会在这个线程中运行。当我们在进行网络连接等比较耗时的操作时,如果此连接动作直接在主线程,也就是UI线程中处理,会发生什么情况呢?整个程序处于等待状态,界面似乎是“假死”掉了。如果5秒钟以上没有响应,系统就会弹出对话框提示是否要强制关闭应用。为了给用户更好的用户体验,必须把这个任务放置到单独线程中运行,避免阻塞UI线程,这样就不会对主线程有任何影响。

8.4.1 多线程和异步处理简介

一般的,网络请求都需要一定的时间,所以在网络开发的过程中,会考虑使用多线程来实现网络请求,配合异步处理完成UI线程的更新。所以我们在本章用一个小节来详细讲下Android中的多线程和异步处理。

Android实现多线程与异步处理一般有下面两种方式:

1)Handler方式。

2)AsyncTask类实现。

下面我们就会对这两种方式做详细的说明。


经验分享:

一般的,如果应用程序中会大量的创建新的线程,就要考虑使用线程池了。使用线程池可以有效的管理线程。由于本节主要介绍如何在Android网络应用中实现异步处理,所以就不对线程池做展开说明了。

8.4.2 Handler方式

Handler允许用户发送、处理消息和与线程的消息队列相关联的runnable对象。每一个handler实例都与一个单独的线程相关联。每次创建一个新的Handler对象时,它都与创建该对象的线程或者该线程中的消息队列绑定在一起,这样Handler就可以发送消息和runnable对象到消息队列中,并在从消息队列中取出的时候处理它们。详细的说明可以参考“4.3.1消息的传递—Handler的使用”。

下面是通过Handler来异步加载网络图片的完整例子:


//import略

publicclass HandlerTest extends Activity {

publicstatic final int SHOW_PROGRESS = 0;

publicstatic final int REFRESH = 1;

publicstatic final int REMOVE_PROGRESS = 2;

privateProgressBar mProgressBar;

privateImageView img;

privateButton btn;

privateBitmap mBitmap;

privateView.OnClickListener mOnClickListener = new View.OnClickListener(){

@Override

publicvoid onClick(View v) {

intid = v.getId();

switch(id) {

caseR.id.download:

sendMessage(SHOW_PROGRESS);

Thread t =

newThread(newDownload("http://www.google.com/images/google_favicon_128.png"));

// 开启一个线程下载图片

t.start();

break;

}

}

};

privateHandler mHandler = new Handler() {

@Override

publicvoid handleMessage(Message msg) {

switch(msg.what) {

caseSHOW_PROGRESS:

//显示等待界面

mProgressBar.setVisibility(View.VISIBLE);

break;

caseREMOVE_PROGRESS:

//隐藏等待界面

mHandler.removeMessages(SHOW_PROGRESS);

mProgressBar.setVisibility(View.INVISIBLE);

break;

caseREFRESH:

//更新UI

onRefresh();

break;

}

}

};

protectedvoid onRefresh() {

if(mBitmap!= null){

//更新UI

img.setImageBitmap(mBitmap);

}

//隐藏等待界面

sendMessage(REMOVE_PROGRESS);

}

protectedfinal void sendMessage(int what) {

mHandler.sendMessage(mHandler.obtainMessage(what));

}

@Override

publicvoid onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.handlertest_layout);

img= (ImageView)findViewById(R.id.imgic);

btn= (Button)findViewById(R.id.download);

btn.setOnClickListener(mOnClickListener);

mProgressBar= new ProgressBar(this);

FrameLayout.LayoutParamsparams = new FrameLayout.LayoutParams(

LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);

params.gravity= Gravity.CENTER;

//添加一个等待的view

addContentView(mProgressBar,params);

//开始时候设置为隐藏

mProgressBar.setVisibility(View.INVISIBLE);

}

/**

* 下载的线程

*/

publicclass Download implements Runnable {

privateString uri;

publicDownload(String uri) {

this.uri= uri;

}

@Override

publicvoid run() {

try{

URL url = new URL(uri);

HttpURLConnectionconn

=(HttpURLConnection)url.openConnection();

conn.setDoInput(true);

conn.connect();

InputStreaminputStream=conn.getInputStream();

mBitmap= BitmapFactory.decodeStream(inputStream);

//下载完成后,发送消息给主线程刷新UI

sendMessage(REFRESH);

}catch (Exception e) {

//

}

}

}

}

具体的Layout文件handlertest_layout.xml代码如下:


<?xmlversion="1.0" encoding="utf-8"?>

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:background="@android:color/white">

<Button

android:id="@+id/download"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="开始下载图片"/>

<ImageView

android:id="@+id/imgic"

android:layout_width="fill_parent"

android:layout_height="wrap_content" />

</LinearLayout>

程序运行结果如下图8-3所示。

图8-3异步加载网络图片的运行效果图


经验分享:

Message是线程之间传递信息的载体,包含了对消息的描述和任意的数据对象。Message中包含了两个额外的intwhat字段(该字段是用来区分每条信息)和一个object字段,这样在大部分情况下,使用者就不需要再做内存分配工作了。虽然Message的构造函数是public的,但是最好是使用Message.obtain()或Handler.obtainMessage()函数来获取Message对象,因为Message的实现中包含了回收再利用的机制,可以提高效率。

8.4.3AsyncTask类实现后台任务的处理

Android提供了一个较线程更简单的处理多任务的方法——AsyncTask异步任务类,相对于线程来说,AsyncTask对于简单的任务处理更安全。AsyncTask类是一个抽象类,你要使用它,必须继承它并实现doInBackground()方法。

AsyncTask<Params,Progress, Result>使用三种泛型和可变参数类型Params,Progress和Result。

  • Params启动任务执行的输入参数,比如HTTP请求的URL。
  • Progress后台任务执行的百分比。
  • Result后台执行任务最终返回的结果,比如String。

AsyncTask主要有三个操作方法

1)doInBackground(Params...),将在onPreExecute方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作,例如网络获取图片。可以调用publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。

2)onProgressUpdate(Progress...),在publishProgress方法被调用后,UIthread将调用这个方法从而在界面上展示任务的进展情况,例如(刷新前台的图片)。

3)onPostExecute(Result),在doInBackground执行完成后,onPostExecute方法将被UIthread调用,后台的计算结果将通过该方法传递到UIthread。

下面我们来看一个下载网页的例子。

首先建一个layout文件asynctask_layout.xml。


<LinearLayoutxmlns:android=”http://schemas.android.com/apk/res/android”

android:layout_width=”match_parent”

android:layout_height=”match_parent”

android:orientation=”vertical”>

<Button

android:id=”@+id/readWebpage”

android:layout_width=”match_parent”

android:layout_height=”wrap_content”

android:onClick=”readWebpage”

android:text=”LoadWebpage” >

</Button>

<TextView

android:id=”@+id/TextView01”

android:layout_width=”match_parent”

android:layout_height=”match_parent”

android:text=”ExampleText” >

</TextView>

</LinearLayout>

下面建一个执行的Activity。


//import略

publicclass AsyncTaskTest extends Activity {

privateTextView textView;

@Override

publicvoid onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.asynctask_layout);

textView= (TextView) findViewById(R.id.TextView01);

}

privateclass DownloadWebPageTask extends AsyncTask<String, Void,String> {

@Override

protectedString doInBackground(String... urls) {

Stringresponse = "";

for(String url : urls) {

// 循环的获取Params中的参数

DefaultHttpClientclient = new DefaultHttpClient();

HttpGethttpGet = new HttpGet(url);

try{

HttpResponseexecute = client.execute(httpGet);

InputStreamcontent = execute.getEntity().getContent();

BufferedReaderbuffer = new BufferedReader(

newInputStreamReader(content));

Strings = "";

while((s = buffer.readLine()) != null) {

response+= s;

}

}catch (Exception e) {

e.printStackTrace();

}

}

returnresponse;

}

@Override

protectedvoid onPostExecute(String result) {

//更新UI

//这里的参数是doInBackground返回过来的

textView.setText(result); }

}

publicvoid readWebpage(View view) {

//按钮的动作

DownloadWebPageTasktask = new DownloadWebPageTask();

task.execute(newString[] { "http://www.baidu.com"});

}

}


经验分享:

在使用AsyncTask中需要注意以下几点:

1)AsyncTask的实例必须在UIthread中创建。

2)AsyncTask.execute方法必须在UIthread中调用。

3)不要手动的调用onPreExecute(),onPostExecute(Result),

doInBackground(Params...),onProgressUpdate(Progress...)这几个方法。

4)该task只能被执行一次,否则多次调用时将会出现异常。

时间: 2024-10-13 00:15:41

第八章 网络的时代—网络开发(3)的相关文章

第八章 网络的时代—网络开发(4)

8.5轻量级的数据交换格式-JSON 8.5.1 client与server端的数据交互 在Android应用开发中,尤其是网络应用的开发,我们常常须要从网络上获取数据,而不只从本地数据库或者本地文件里取得数据,这个时候就涉及到client与server端的数据交互了.client怎样须要与server端进行数据交互.就须要约定一种协议或者是数据交换格式. 那么一般的.Androidclient与server端进行数据交互有哪些方式呢?依据业务需求的不同,可能会选用不用的方式,通常有以下几种方式

第八章 网络的时代—网络开发(2)

8.3基于最成熟的Web协议-HTTP协议编程 8.3.1 HTTP协议简单介绍 超文本传输协定(HTTP.HyperTextTransferProtocol)是互联网上应用最为广泛的一种网络协议. 全部的WWW文件都必须遵守这个标准.设计HTTP最初的目的是为了提供一种公布和接收HTML页面的方法. HTTP是一个client和server端请求和应答的标准(TCP).client是终端用户,server端是站点.通过使用Web浏览器.网络爬虫或者其它的工具,client发起一个到server

微信营销是网络经济时代企业对营销模式的创新

小微信,大商机 ·截止目前,中国手机用户已经突破12亿,微信用户已经突破6亿! ·如果你错过了10年前的互联网,就不应该错过电子商务! ·如果你错过了5年前电子商务,就不要再错过移动互联网! ·微信已经成为移动互联网上的"超级入口"! ·微信时代,蕴藏着移动互联网的巨大商机! ·        案例1:小米开通微信商城,短短9分55秒,15万台小米手机3即被抢购一空! ·        案例2:杭州某知名服装品牌女装网店近1/3销量订单在微信上成交! ·        案例3:广州三名

2019.03.30 云计算和大数据时代网络技术揭秘

云计算  大数据   时代 来源<云计算和大数据时代网络技术揭秘> 第一章 云计算的兴起 云计算的本质是一种服务提供模型,通过这种模型可以随时,随地,按需地通过网络访问共享资源池的资源,这个资源池的内容包括计算资源,网络资源,存储资源等,这些资源你能够被动态的分配和调整,在不同用户之间灵活的划分.范式符合这些特征的IT服务都可以称为云计算服务 为了能将这个定义更方便的匹配到显示世界的IT架构中: IaaS 通过虚拟化技术奖服务器等计算平台同存储和网络资源打包,通过API接口的形式提供给用户.用

【大数据】大数据时代--网络数据与科学的时代

大数据_大数据时代_大数据概念_网络大数据 随着大数据时代的来临,大数据也吸引了越来越多的关注.网络大数据(http://www.raincent.com)整合了大数据,大数据概念,大数据处理,大数据分析,cdn,cdn加速,idc,网络测量,网络监测,网络安全测量,网站性能监测,行业分析报告,行业研究报告,免费行业报告等服务为一体,力争打造中国最大的网络大数据中心. 这两个词最早出现是在上世纪90年代.按照当时的解释,大科学时代主要是指单打独斗的时代结束了,要搞集团军式的科研.也有一种说法是,

网络小助手项目开发总结报告

网络小助手项目开发总结报告 1引言 1.1编写目的 通过一段时间后对网络小助手项目进行详细开发和测试,该项目已经基本完成.本报告旨在将项目开发过程中的经验和不足之处进行总结,为以后的团队开发活动积累经验.本报告经审核后,交由软件工程老师王老师审查. 1.2背景 说明: a.  软件项目名称:网络小助手 b.  开发者:兰梦,李金吉,马翔,赵天,胡佳奇 用户:学生 系统运行环境:windows XP/windows 7/windows 8下的通用PC 1.3参考资料 <软件工程--原理,方法与应用

通过nfs网络文件系统启动tiny6410开发板时uboot启动参数的设置 &nbsp;

通过nfs网络文件系统启动tiny6410开发时uboot启动参数应该设置为: console=ttySAC0 lcd=S70 root=/dev/nfs nfsroot=192.168.1.30:/opt/tiny6410/fs/rootfs_mini6410 ip=192.168.1.40:192.168.1.30:192.168.1.30:255.255.255.0:tiny6410:eth0:off 注意:这里一定要指明你的lcd的类型,不然通过nfs成功启动tiny6410时,你的lc

Unity网络多玩家游戏开发教程第1章Unity自带网络功能

Unity网络多玩家游戏开发教程第1章Unity自带网络功能 Unity拥有大量的第三方插件,专门提供了对网络功能的支持.但是,大部分开发者第一次接触到的还是Unity自带的网络功能,也就是大家经常说到的Unity Networking API.这些API是借助于组件NetworkView发挥作用的,而它可以简化开发者大量的网络功能编码任务.本文选自<Unity网络多玩家游戏开发教程(大学霸内部资料)> NetworkView组件 在Unity中,NetworkView组件用于处理游戏在网络上

网络支付区块链开发,搭建区块链支付平台

随着区块链支付的发展,区块链分布式账本技术将区块链上数字资.产流动与现实的现.金支付相连接.在全球互联网市场上能够发挥出传统金融机构无法替代的高效率.低成本的价值传递的作用.每个人的密码钱.包就可以发展成一个"自.金.融"平台,可以用于P.2.P 的支.付.存.款.转.账.换.汇.借.贷以及全.网.记.账.清.算.支付是金.融交易中必不可少的一个环节.在信息技术和金融业务不断融合的大趋势下,网络支付体系和网络支付的方法发生了深刻的变化,网络支付的理论和实践正在向泛中心化的网络支付聚焦,