一:ANR现象:
==应用程序无响应<Application not Responsed>==
1.单线程模型的原则:
- 主线程UI不能被阻塞
- 非主线程不能更新UI
public class MainActivity extends Activity{
private TextView textView;
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInatanceState);
setContentView(R.layout.main_activity);
//违反第二原则:在非主线程更新UI
//CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
new Thread(){
public void run(){
int count = 0;
while(count < 100){
count ++ ;
try{
Thread.sleep(1000);
}
catch(Exception e){
e.printStackTrace;
}
//在非UI线程更新UI
textView.setText("当前count:"+count);
}
};
}.start();
}
//违反第一个原则,导致ANR现象出现
public void click(View view){
try{
Thread.sleep(6000);
}
catch(Exception e){
e.printStackTrace();
}
}
}
二.AsyncTask的基本使用
1.自定义一个类继承系统的AsyncTask,其参数说明如下:
- Params:启动异步任务执行的输入参数 例如HTTP请求的URL一般是String类型
- Progress:后台执行任务的百分比 通常是Integer类型
- Result:后台执行任务最终返回的结果
==注意:AsyncTask的执行分为四个步骤 每一步都对应一个回调方法(由应用程序自动调用的方法) 开发者需要做的就是实现这些方法==
2.为了正确的使用AsyncTask类,必须遵守以下几条准则:
- AsyncTask的实例必须在UI线程中创建
- execute方法必须在UI线程中调用
- 不要手动去调用onPreExecute() doInBaground() onProgressUpdate() onPostExecute()
- AsyncTask的实例只能被执行一次 多次调用的时候将会出现异常
==代码:首先自定义一个类实现系统AsyncTask,异步图片下载:==
public class MyAsyncTask extends AsyncTask<String , Void , Bitmap>{
//上下文对象
private Context context;
private ProgressDialog dialog;
private ImageView imageView;
//构造
public MyAsyncTask(Context context , ImageView imageView){
super();
this.context = context;
this.imageView = imageView;
}
/**
* 实现四个系统回调的方法
*/
/**
* 1.onPreExecute()方法:在后台执行前的准备工作,主线程调用
* 准备工作:做什么?>创建进度对话框
*/
@Override
protected void onPreExecute(){
super.onPreExecute();
dialog = new ProgressDialog();
dialog.setIcon(R.drawable.xxx);
dialog.setTitle("友情提示!");
dialog.setMessage("正在玩命为您加载中");
//下面show()方法不要忘了,否则不显示进度对话框
dialog.show();
}
/**
* 2.doInBackground()方法:非主线程调用,后台的主要工作线程,
* 如耗时的操作(网络下载图片,下载JSON等)都放在这里执行。
* 它是子线程,不可以在这里做UI操作(重要)
* 参数是String类型字符数组,通常为传入的url
*/
@Override
public void doInBackground(String...params){
//网络请求:
/*创建HttpClient的实例*/
HttpClient httpClient = new DefaultHttpClient();
/*创建连接方法的实例,HttpGet()的构造中传入url地址*/
HttpGet httpGet = new HttpGet(params[0]);
try{
/*调用创建好的HttpClient的实例的execute方法来发送创建好的HttpGet或HttpPost请求,并返回HttpResponse对象*/
HttpResponse httpResponse = httpClient.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode() == 200){
/*返回实体对象*/
HttpEntity entity = httpResponse.getEntity();
byte [] data = EntityUtils.toByteArray(entity);
Bitmap bitmap = BitmapFactory.decodeByteArray(data,0,data.length);
return bitmap;
}
}
catch(Exception e){
e.printStackTrace();
}
finally{
httpClient.getConnectionManager().shutdown();
}
}
/**
* 更新显示进度,主线程调用
*/
@Override
public void onProgressUpdate(Void...values){
super.onProgressUpdate(values);
}
/**
* 在doInBackground执行完成之后调用,后台的计算结果将通过该方法传递到UI线程,回到主线程(主线程调用的)
* 可以实现主线程和子线程之间的数据交互
*/
public void onPostExcute(Bitmap bitmap){
super.onPostExecute(bitmap);
if(bitmap != null){
imageView.setImageBitmap(bitmap);
}
else{
Toast.makeText(context,"下载图片失败",Toast.LENGTH.LONG).show();
}
//关闭进度对话框
dialog.dismiss();
}
}
测试代码:
public class MainActivity extends Activity{
private ImageView imageView;
private MyAsyncTask myAsyncTask;
private String url = "";http://p5.qhimg.com/dmt/490_350_/t01405cf23f986e5ef6.jpg
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
imageView = (ImageView)findViewById(R.id.iv_imageview);
//创建AsyncTask的实例
myAsyncTask = new MyAsyncTask(this,imageView);
}
//点击按钮,开始异步下载图片
public void downloadPic(View view){
/*AsyncTask的实例只能被执行一次*/
myAsyncTask.execute(url);
}
}