导读:oInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定,第一个为doInBackground接受的参数,第二个为显示进度的参数,第第三个为doInBackground返回和onPostExecut
在开发Android应用时必须遵守单线程模型的原则:
UI操作并不是线程安全的并且这些操作必须在UI线程中执行。
在单线程模型中始终要记住两条法则:
1. 不要阻塞UI线程
2. 确保只在UI线程中访问Android UI工具包
当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程。
比如说从网上获取一个网页,在一个TextView中将其源代码显示出来,这种涉及到网络操作的程序一般都是需要开一个线程完成网络访问,但是在获得页面源码后,是不能直接在网络操作线程中调用
TextView.setText()的.因为其他线程中是不能直接访问主UI线程成员 。
android提供了几种在其他线程中访问UI线程的方法。
Activity.runOnUiThread( Runnable )
View.post( Runnable )
View.postDelayed( Runnable, long )
Hanlder
这些类或方法同样会使你的代码很复杂很难理解。然而当你需要实现一些很复杂的操作并需要频繁地更新UI时这会变得更糟糕。
为了解决这个问题,Android 提供了一个工具类:AsyncTask
它使创建需要与用户界面交互的长时间运行的任务变得更简单。
相对来说AsyncTask更轻量级一些,适用于简单的异步处理,不需要借助线程和Handler即可实现。
AsyncTask是抽象类.AsyncTask定义了三种泛型类型 Params,Progress和Result。
Params 启动任务执行的输入参数,比如HTTP请求的URL。
Progress 后台任务执行的百分比。
Result 后台执行任务最终返回的结果,比如String。
AsyncTask的执行分为四个步骤,每一步都对应一个回调方法,这些方法不应该由应用程序调用,开发者需要做的就是实现这些方法。
1) 子类化AsyncTask
2) 实现AsyncTask中定义的下面一个或几个方法
onPreExecute(), 该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条。
doInBackground(Params…), 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。
onProgressUpdate(Progress…),在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
onPostExecute(Result), 在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,后台的计算结果将通过该方法传递到UI thread.
为了正确的使用AsyncTask类,以下是几条必须遵守的准则:
1) Task的实例必须在UI thread中创建
2) execute方法必须在UI thread中调用
3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params…), onProgressUpdate(Progress…)这几个方法
4) 该task只能被执行一次,否则多次调用时将会出现异常
doInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定,第一个为doInBackground接受的参数,第二个为显示进度的参数,第第三个为doInBackground返回和onPostExecute传入的参数。
从网上获取一个网页,在一个TextView中将其源代码显示出来
001 |
package test.list; |
002 |
|
003 |
import java.io.ByteArrayOutputStream; |
004 |
|
005 |
import java.io.InputStream; |
006 |
|
007 |
import java.util.ArrayList; |
008 |
|
009 |
import org.apache.http.HttpEntity; |
010 |
|
011 |
import org.apache.http.HttpResponse; |
012 |
|
013 |
import org.apache.http.client.HttpClient; |
014 |
|
015 |
import org.apache.http.client.methods.HttpGet; |
016 |
|
017 |
import org.apache.http.impl.client.DefaultHttpClient; |
018 |
|
019 |
import android.app.Activity; |
020 |
|
021 |
import android.app.ProgressDialog; |
022 |
|
023 |
import android.content.Context; |
024 |
|
025 |
import android.content.DialogInterface; |
026 |
|
027 |
import android.os.AsyncTask; |
028 |
|
029 |
import android.os.Bundle; |
030 |
|
031 |
import android.os.Handler; |
032 |
|
033 |
import android.os.Message; |
034 |
|
035 |
import android.view.View; |
036 |
|
037 |
import android.widget.Button; |
038 |
|
039 |
import android.widget.EditText; |
040 |
|
041 |
import android.widget.TextView; |
042 |
|
043 |
public class NetworkActivity extends Activity{ |
044 |
|
045 |
private TextView message; |
046 |
|
047 |
private Button open; |
048 |
|
049 |
private EditText url; |
050 |
|
051 |
@Override |
052 |
|
053 |
public void onCreate(Bundle savedInstanceState) { |
054 |
|
055 |
super .onCreate(savedInstanceState); |
056 |
|
057 |
setContentView(R.layout.network); |
058 |
|
059 |
message= (TextView) findViewById(R.id.message); |
060 |
|
061 |
url= (EditText) findViewById(R.id.url); |
062 |
|
063 |
open= (Button) findViewById(R.id.open); |
064 |
|
065 |
open.setOnClickListener( new View.OnClickListener() { |
066 |
|
067 |
public void onClick(View arg0) { |
068 |
|
069 |
connect(); |
070 |
|
071 |
} |
072 |
|
073 |
}); |
074 |
|
075 |
|
076 |
} |
077 |
|
078 |
private void connect() { |
079 |
|
080 |
PageTask task = new PageTask( this ); |
081 |
|
082 |
task.execute(url.getText().toString()); |
083 |
|
084 |
} |
085 |
|
086 |
class PageTask extends AsyncTask<String, Integer, String> { |
087 |
|
088 |
// 可变长的输入参数,与AsyncTask.exucute()对应 |
089 |
|
090 |
ProgressDialog pdialog; |
091 |
|
092 |
public PageTask(Context context){ |
093 |
|
094 |
pdialog = new ProgressDialog(context, 0 ); |
095 |
|
096 |
pdialog.setButton( "cancel" , new DialogInterface.OnClickListener() { |
097 |
|
098 |
public void onClick(DialogInterface dialog, int i) { |
099 |
|
100 |
dialog.cancel(); |
101 |
|
102 |
} |
103 |
|
104 |
}); |
105 |
|
106 |
pdialog.setOnCancelListener( new DialogInterface.OnCancelListener() { |
107 |
|
108 |
public void onCancel(DialogInterface dialog) { |
109 |
|
110 |
finish(); |
111 |
|
112 |
} |
113 |
|
114 |
}); |
115 |
|
116 |
pdialog.setCancelable( true ); |
117 |
|
118 |
pdialog.setMax( 100 ); |
119 |
|
120 |
pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); |
121 |
|
122 |
pdialog.show(); |
123 |
|
124 |
} |
125 |
|
126 |
@Override |
127 |
|
128 |
protected String doInBackground(String... params) { |
129 |
|
130 |
try { |
131 |
|
132 |
HttpClient client = new DefaultHttpClient(); |
133 |
|
134 |
// params[0]代表连接的url |
135 |
|
136 |
HttpGet get = new HttpGet(params[ 0 ]); |
137 |
|
138 |
HttpResponse response = client.execute(get); |
139 |
|
140 |
HttpEntity entity = response.getEntity(); |
141 |
|
142 |
long length = entity.getContentLength(); |
143 |
|
144 |
InputStream is = entity.getContent(); |
145 |
|
146 |
String s = null ; |
147 |
|
148 |
if (is != null ) { |
149 |
|
150 |
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
151 |
|
152 |
byte [] buf = new byte [ 128 ]; |
153 |
|
154 |
int ch = - 1 ; |
155 |
|
156 |
int count = 0 ; |
157 |
|
158 |
while ((ch = is.read(buf)) != - 1 ) { |
159 |
|
160 |
baos.write(buf, 0 , ch); |
161 |
|
162 |
count += ch; |
163 |
|
164 |
if (length > 0 ) { |
165 |
|
166 |
// 如果知道响应的长度,调用publishProgress()更新进度 |
167 |
|
168 |
publishProgress(( int ) ((count / ( float ) length) * 100 )); |
169 |
|
170 |
} |
171 |
|
172 |
|
173 |
|
174 |
// 让线程休眠100ms |
175 |
|
176 |
Thread.sleep( 100 ); |
177 |
|
178 |
} |
179 |
|
180 |
s = new String(baos.toByteArray()); } |
181 |
|
182 |
// 返回结果 |
183 |
|
184 |
return s; |
185 |
|
186 |
} catch (Exception e) { |
187 |
|
188 |
e.printStackTrace(); |
189 |
|
190 |
} |
191 |
|
192 |
return null ; |
193 |
|
194 |
} |
195 |
|
196 |
@Override |
197 |
|
198 |
protected void onCancelled() { |
199 |
|
200 |
super .onCancelled(); |
201 |
|
202 |
} |
203 |
|
204 |
@Override |
205 |
|
206 |
protected void onPostExecute(String result) { |
207 |
|
208 |
// 返回HTML页面的内容 |
209 |
|
210 |
message.setText(result); |
211 |
|
212 |
pdialog.dismiss(); |
213 |
|
214 |
} |
215 |
|
216 |
@Override |
217 |
protected void onPreExecute() { |
218 |
|
219 |
// 任务启动,可以在这里显示一个对话框,这里简单处理 |
220 |
|
221 |
message.setText(R.string.task_started); |
222 |
|
223 |
} |
224 |
|
225 |
@Override |
226 |
|
227 |
protected void onProgressUpdate(Integer... values) { |
228 |
|
229 |
// 更新进度 |
230 |
|
231 |
System.out.println( "" +values[ 0 ]); |
232 |
|
233 |
message.setText( "" +values[ 0 ]); |
234 |
|
235 |
pdialog.setProgress(values[ 0 ]); |
236 |
|
237 |
} |
238 |
|
239 |
} |
240 |
|
241 |
} |