一、AsyncTask
①AsyncTask的源码:
public abstract class AsyncTask<Params, Progress, Result>
三种泛型类型分别代表“启动任务执行的输入参数”、“后台任务执行的进度”、“后台计算结果的类型”。
②相关的方法:
一个异步任务的执行一般包括以下几个步骤:
1.execute(Params... params),执行一个异步任务,需要我们在代码中调用此方法,触发异步任务的执行。
2.onPreExecute(),在execute(Params... params)被调用后立即执行,一般用来在执行后台任务前对UI做一些标记。
3.doInBackground(Params... params),在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。
4.onProgressUpdate(Progress... values),在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。
5.onPostExecute(Result result),当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。
在使用的时候,有几点需要格外注意:
1.异步任务的实例必须在UI线程中创建。
2.execute(Params... params)方法必须在UI线程中调用。
3.不要手动调用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)这几个方法。
4.不能在doInBackground(Params... params)中更改UI组件的信息。
5.一个任务实例只能执行一次,如果执行第二次将会抛出异常。
(注:找资料的时候,看到挺详细的挺不错。 以上面内容转自:http://blog.csdn.NET/liuhe688/article/details/6532519)
二、案例
1、首先我们创建一个名为multithreadcho1的项目:
实现功能:
点击一个按钮,每隔3秒跟新一行item数据,进度条也显示,更新玩数据后改变TextView控件的值。
activity_main.xml布局文件:
<TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/textView1" android:layout_marginLeft="72dp" android:layout_toRightOf="@+id/textView1" android:text="test" /> <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/button1" android:layout_marginTop="84dp" > </ListView> <ProgressBar android:id="@+id/progressBar1" style="?android:attr/progressBarStyleHorizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/listView1" android:layout_alignRight="@+id/button1" android:layout_below="@+id/button1" android:layout_marginTop="28dp" />
图片:
item.xml布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <TextView android:id="@+id/username" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="25dp" android:textSize="25dp" /> <TextView android:id="@+id/sex" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="25dp" android:textSize="25dp" /> </LinearLayout>
图片:
这两个TextView用来显示姓名和性别。
首先创建一个Userinfos类用来封装表的,添加两个字段 Name 和Sex。
Userinfos.java文件:
MainActivity.java文件:
public class MainActivity extends Activity { private SimpleAdapter sa; private Button btn; private TextView tv; private List<Userinfos> list=new ArrayList<Userinfos>(); private BaseAdapter adapter; private ListView lv; @Override protected void onCreate(Bundle savedInstanceState) { //这里是UI主线程 super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); for (int i = 0; i < 5; i++) { Userinfos u = new Userinfos(); u.setName("小明"+i); u.setSex("男"+i); list.add(u); } lv=(ListView)this.findViewById(R.id.listView1); tv=(TextView)findViewById(R.id.textView1); btn=(Button)findViewById(R.id.button1); btn.setOnClickListener(new OnClickListener(){ //模拟数据访问产生数据 @Override public void onClick(View v) { // TODO Auto-generated method stub Take tk=new Take(MainActivity.this); tk.execute(list,adapter);//参数是传给doInBackground }}); adapter=new BaseAdapter(){ @Override public int getCount() { // TODO Auto-generated method stub return list.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub LayoutInflater inflater = MainActivity.this.getLayoutInflater(); View vw; if(convertView==null) { Log.i("View","创建对象"); vw = inflater.inflate(R.layout.item, null); } else { vw=convertView; } TextView tv_username = (TextView)vw.findViewById(R.id.username); TextView tv_sex = (TextView)vw.findViewById(R.id.sex); tv_username.setText(list.get(position).getName()); tv_sex.setText(list.get(position).getSex()); return vw; }}; lv.setAdapter(adapter); }
创建一个Take类继承AsyncTask,进行异步任务操作。
Take.java文件:
public class Take extends AsyncTask{ private MainActivity activity; private BaseAdapter adapter; private List<Userinfos> list=new ArrayList<Userinfos>(); protected Take(MainActivity activity) { this.activity=activity; } //后台运行(数据库,蓝牙,互联网) @Override protected Object doInBackground(Object... params) { // TODO Auto-generated method stub list = (List<Userinfos>) params[0]; Log.i("list",""+list.size()); adapter = (BaseAdapter) params[1]; for(int i=0;i<list.size();i++) { publishProgress(i); //这里的参数类型是 AsyncTask<Void, Integer, Void>中的Integer决定的, //在onProgressUpdate中可以得到这个值去更新UI主线程,这里是异步线程 。 Log.i("time","休眠"); try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } list.get(i).setName("小红"+i); list.get(i).setSex("女"+i); } return "天气:22度"; } //准备 @Override protected void onPreExecute() { Toast.makeText(activity, "今晚有约", Toast.LENGTH_SHORT).show(); super.onPreExecute(); } //做完后执行 @Override protected void onPostExecute(Object result) { //result的值为doInBackground方法的返回值 String tr=result.toString(); TextView tv = (TextView)activity.findViewById(R.id.textView1); tv.setText("访问完成!"+tr); // TODO Auto-generated method stub super.onPostExecute(result); } //分步完成 //onProgressUpdate更新进度条 @Override protected void onProgressUpdate(Object... values) { // TODO Auto-generated method stub Log.i("dd","进入分步"); int bar= Integer.parseInt(values[0].toString()); bar=(bar+1)*20; ProgressBar progressBar = (ProgressBar)activity.findViewById(R.id.progressBar1); progressBar.setProgress(bar); adapter.notifyDataSetChanged(); //这里是UI主线程 } }
1、通过继承AsyncTask,进行相关异步任务操作
2、调用 publishProgress(i)方法进入onProgressUpdate进度条更新的方法,通过BaseAdapter的notifyDataSetChanged()方法通知更新数据。
3、数据更新完后进入onPostExecute方法,该方法的result参数的值为doInBackground方法的返回值,我们固定让它返回字符串。
4、将doInBackground方法返回的值赋给TextView。
效果图片: