在上篇博文中我们讲到多线程之间通信的第一种办法,即通过使用handler,而在本篇博文中,我们重点来讲讲其中的第二种办法,使用AsyncTask来完成多线程通信.
AsyncTask:异步任务,从字面上来说,就是在我们的UI主线程运行的时候,异步的完成一些操作。AsyncTask允许我们的执行一个异步的任务在后台。我们可以将耗时的操作放在异步任务当中来执行,并随时将任务执行的结果返回给我们的UI线程来更新我们的UI控件。通过AsyncTask我们可以轻松的解决多线程之间的通信问题。
怎么来理解AsyncTask呢?通俗一点来说,AsyncTask就相当于Android给我们提供了一个多线程编程的一个框架,其介于Thread和Handler之间,我们如果要定义一个AsyncTask,就需要定义一个类来继承AsyncTask这个抽象类,并实现其唯一的一个 doInBackgroud 抽象方法。要掌握AsyncTask,我们就必须要一个概念,总结起来就是: 3个泛型,4个步骤。
3个泛型指的是什么呢?我们来看看AsyncTask这个抽象类的定义,当我们定义一个类来继承AsyncTask这个类的时候,我们需要为其指定3个泛型参数:
AsyncTask
package com.wust.asy;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.SimpleAdapter;
import android.widget.Toast;
public class MainActivity extends Activity {
private final int SUCCESS = 0;//加载成功
private final int NONEWS = 1;//该栏目下没有新闻
private ListView lv;
private Button btn;
private ProgressBar pb;
private String path1="http://www.cnwust.com/index.html";
private List<Map<String, Object>> list;
private SimpleAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.lv);
btn = (Button) findViewById(R.id.titlebar_refresh);
pb = (ProgressBar) findViewById(R.id.loadnews_progress);
list = new ArrayList<Map<String,Object>>();
adapter = new SimpleAdapter(this,list,R.layout.list_ltem,
new String[]{"images","titles"},
new int[]{R.id.images,R.id.titles});
lv.setAdapter(adapter);
btn.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
MyAsyncTask my=new MyAsyncTask();
my.execute(path1);
}
});
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
Intent intent = new Intent(MainActivity.this, NewsDetailsActivity.class);
//把需要的信息放到Intent中
Bundle bundle=new Bundle();
bundle.putString("newsDate", list.get(position).get("link").toString());
bundle.putString("titles", list.get(position).get("titles").toString());
intent.putExtras(bundle);
startActivity(intent);
}
});
}
public class MyAsyncTask extends AsyncTask<String, Integer, Integer> {
@Override
protected void onPreExecute() {
super.onPreExecute();
//隐藏刷新按钮
btn.setVisibility(View.GONE);
//显示进度条
pb.setVisibility(View.VISIBLE);
//设置LoadMore Button 显示文本
//mLoadMoreBtn.setText(R.string.loadmore_txt);
}
@Override
protected Integer doInBackground(String... path1) {
Document doc;
try {
doc = Jsoup.connect("http://www.cnwust.com/index.html").get();
Elements elements=doc.select("#inner_nav a");
Log.i("3",elements.toString());
for(int i=1;i<elements.size();i++ )
{
Map<String, Object> map=new HashMap<String, Object>();
map.put("images", R.drawable.ic_launcher);
map.put("titles", elements.get(i).text());
map.put("link", elements.get(i).attr("abs:href"));
list.add(map);
}
} catch (IOException e) {
e.printStackTrace();
return NONEWS;
}
return SUCCESS;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(Integer values) {
switch(values){
case NONEWS:
Toast.makeText(MainActivity.this, "sorry,没有新闻", Toast.LENGTH_LONG).show();
case SUCCESS:
Toast.makeText(MainActivity.this, "加载成功", Toast.LENGTH_LONG).show();
}
adapter.notifyDataSetChanged();
//显示刷新按钮
btn.setVisibility(View.VISIBLE);
//隐藏进度条
pb.setVisibility(View.GONE);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
执行的效果:
由于本文重点是为了着重讲讲AsyncTask的运行机制,所以对界面实现的效果比较简洁,我们通过点击刷新按钮,来实现从我们网上抓取数据的这个耗时操作,在得到数据之前,我们使用进度条来表示我们主线程当前UI状态
protected void onPreExecute() {
super.onPreExecute();
//隐藏刷新按钮
btn.setVisibility(View.GONE);
//显示进度条
pb.setVisibility(View.VISIBLE);
//设置LoadMore Button 显示文本
//mLoadMoreBtn.setText(R.string.loadmore_txt);
}
在获取到数据之后,然后写到list里面,再在耗时操作完后对应的这个方法里面及时更新当前的UI
protected void onPostExecute(Integer values) {
switch(values){
case NONEWS:
Toast.makeText(MainActivity.this, "sorry,没有新闻", Toast.LENGTH_LONG).show();
case SUCCESS:
Toast.makeText(MainActivity.this, "加载成功", Toast.LENGTH_LONG).show();
}
adapter.notifyDataSetChanged();
//显示刷新按钮
btn.setVisibility(View.VISIBLE);
//隐藏进度条
pb.setVisibility(View.GONE);
}
注意,这里只需要调用适配器adapter的notifyDataSetChanged()即可,不需要进行其他的操作.
在实际操作中,我们有时不需要一定要按照AsyncTask的三个参数定义的意义来重新套用,可以灵活的变通使用,只要代码能到达我们想要的效果就行,在上段实例代码中,我们定义的三个参数就与它们的本义没有多大联系
最后要注意的是在使用AsyncTask做异步任务的时候必须要遵循的原则:
1.AsyncTask类必须在UI Thread当中加载,在Android Jelly_Bean版本后这些都是自动完成的
2.AsyncTask的对象必须在UI Thread当中实例化
3.execute方法必须在UI Thread当中调用
4.不要手动的去调用AsyncTask的onPreExecute, doInBackground, publishProgress, onProgressUpdate, onPostExecute方法,这些都是由Android系统自动调用的
5.AsyncTask任务只能被执行一次
关于对AsyncTask的讲解就到此为止了,本片博文的部分内容也有参考这片文章,有兴趣爱好的同学可以看看原文:
http://www.cnblogs.com/xiaoluo501395377/p/3430542.html