现在的位置: 首页 > 综合 > 正文

Asynctask解析

2018年02月16日 ⁄ 综合 ⁄ 共 2868字 ⁄ 字号 评论关闭

AsyncTask

AsyncTask中有三个参数(例如class MyTask extends AsyncTask<参数1,参数2,参数3>{})

  • 参数1:向后台任务的执行方法传递参数的类型
  • 参数2:在后台任务执行过程中,要求主UI线程处理中间状态,通常是一些UI处理中传递的参数类型
  • 参数3:后台任务执行完返回时的参数类型
    
    

其中参数1和参数2是一个varags,例如String…,相当于String[]。

对于AsyncTask的使用步骤如下:

  • 创建一个AsyncTask的子类,对象创建时带参数(参数1,参数2,参数3)
  • 调用对象的excute()时,将启动后台进程,执行doInBackground()的代码。excute()中所传递的参数类型在参数1中描述,属于范式定义
  • 如果我们希望在启动后台进程中,进行某些初始化的处理,可以override onPreExecute()方法,注意这些代码是在UI线程中执行的
  • 在执行完后台进程,我们需要进行某些处理,例如停止某些UI的动态画面,进度条消失等等,可以重写onPostExecute()方法,同样,这些代码也是在UI主线程中执行。其中将doInBackground()的返回值传递作为onPostExecute()参数中,其类型由参数3描述
  • 在执行后台进程中,如果需要需要向UI线程报告某个处理状态,可以通过publishProgress()来触发,这样在UI主线程中将执行重写后的onProgressUpdate()的代码,其中传递的参数的类型由参数2描述。
    public class Chapter15Test3 extends ListActivity{
        //这里是List Item内容,在这个例子中,将在后台任务中逐个加入
        private static String[] items={"lorem", "ipsum", "dolor","sit", "amet", "consectetuer","adipiscing", "elit", "morbi","vel", "ligula", "vitae","arcu", "aliquet", "mollis","etiam", "vel", "erat","placerat", "ante","porttitor", "sodales","pellentesque", "augue","purus"};
    
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.chapter_8_test2);
            //在这个例子中,我们一开始并没有导入items的数据,注意item数据为新建的ArrayList,即无内容
            setListAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,new ArrayList<String>()));
            //步骤5:创建后台任务的对象,并通过execute()启动后台线程,调用doInBackground()的代码,execute中的参数类型为参数1,这里我们不需要传递任何内容
            new AddStringTask().execute();
        }
      
        //步骤1:创建AsyncTask子类,参数1是Void的范式类型,参数2是String的范式类型,参数3是Void 。其中参数1:向后台任务的执行方法传递参数的类型;参数2:在后台任务执行过程中,要求主UI线程处理中间状态,通常是一些UI处理中传递的参数类型;参数3:后台任务执行完返回时的参数类型。
        private class AddStringTask extends AsyncTask<Void, String,Void>{
           //我们加入一个检测信息的方法,打印当前在哪个线程执行的信息
            private void printInfo(String info){
                Log.d("WEI", info + " : Tread is " + Thread.currentThread().getName());
            }
      
            //步骤2:实现抽象方法doInBackground(),代码将在后台线程中执行,由execute()触发,由于这个例子并不需要传递参数,使用Void...,具体书写方式为范式书写
            protected Void/*参数3*/ doInBackground(Void...params/*参数1*/) {
                for(String item : items){
                    //步骤3:通知UI主线程执行相关的操作(在onProgressUpdate中定义)
                    publishProgress(item/*参数2*/);
                    printInfo("doInBackgound " + item);
                    SystemClock.sleep(200);
                }
                return null;
            }
    
            //步骤3:定义收到pushProgress()触发后,在UI主线程执行的内容,在本例,将item加入list中。方法中的参数为范式方式,实质为数组,由于我们只传递了item一个String,要获取,为values[0]
            protected void onProgressUpdate(String... values/*参数2*/) {
                printInfo("onProgressUpdate  get param " + values[0]);
                ((ArrayAdapter<String>)getListAdapter()).add(values[0]);
            }
          
            //步骤4:定义后台进程执行完后的处理,本例,采用Toast
            protected void onPostExecute(Void result/*参数3*/) {
                printInfo("onPostExecute");
                Toast.makeText(Chapter15Test3.this, "Done!", Toast.LENGTH_SHORT).show();
            }         
        }   
    }

    需要注意

    虽然Android提供后台任务方便我们处理,是否使用后台任务,以及如何使用后台任务,我们要注意下面的内容:

    可能在执行后台线程处理中,用户和UI之间存在交互,这些交换可能会对后台任务有重要的影响,因此需要通知后台线程,Android提供很多的类来处理,封装在java.util.concurrent包中,帮助与后台线程的安全通信。可能在执行后台线程处理中,我们的Activity就已经被kill了,例如有一个电话过来,然后发给短信,查看号码本。这时系统可能将你的activity踢走,接着后面我们会学习Activity的生命周期,了解相关的情况。在编程中,出现这种情况,只要有可能,需要将后台进程关闭。可能在执行后台线程处理中,出现某种错误,例如后台在下载URL,而网络连接中断了。这种情况下关闭后台进程可能是最好的处理。此外后台任务是消耗CPU和内存,是有代价的,我们应该确保它处理的时候更为有效。

抱歉!评论已关闭.