美文网首页
Android-AsyncTask异步任务、

Android-AsyncTask异步任务、

作者: 晴天ccc | 来源:发表于2022-04-04 10:20 被阅读0次

    Android 为什么要引入异步任务

    • Android程序刚启动时,会同时启动一个对应的主线程(Main Thread),这个主线程主要负责处理 与UI相关的事件!有时我们也把他称作UI线程!
    • 假如我们在非UI线程中,比如在主线程中new Thread()另外开辟一个线程,然后直接在里面修改UI控件的值; 此时会抛出下述异常: android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views
    • 如果我们把耗时的操作都放在UI线程中的话,如果UI线程超过5s没有响应用于请求,那么 这个时候会引发ANR(Application Not Responding)异常,就是应用无响应。

    一、为什么要用AsyncTask?

    • 官方给我们提供了AsyncTask这个封装好的轻量级异步类,通过几十行的代码就可以完成 我们的异步操作,而且进度可控。
    • 实际异步用的最多的地方就是网络操作,图片加载,数据传输等。

    注意事项

    • Task的实例必须在UI thread中创建。
    • execute方法必须在UI thread中调用。
    • 不要手动的调用onPreExecute, onProgressUpdate,doInBackground,onPostExecute这几个方法。
    • 该Task只能被执行一次,否则多次调用时将会出现异尝。

    二、AsyncTask方法讲解:

    新建一个类TestAsyncTask继承AsyncTask,需要指定三个泛型参数。

    public class TestAsyncTask extends AsyncTask<Void, Integer, String>{
    }
    

    第一个参数Params: 开始异步任务执行时传入的参数类型,对应excute()中传递的参数。
    第二个参数Progress: 异步任务执行过程中,返回下载进度值的类型。
    第三个参数Result: 异步任务执行完成后,返回的结果类型,与doInBackground()的返回值类型保持一致。

    /**
     * 第一个参数Parma: 执行异步任务时传入的参数,即doInBackground方法参数类型。
     * 第二个参数Progress: 显示异步任务的进度,选择Integer类型,即onProgressUpdate方法参数类型。
     * 第三个参数Result: 异步任务执行完成后,返回的结果类型。即onPostExecute方法的参数类型与doInBackground()的返回值类型保持一致。
     * 执行顺序:  onPreExecute --> doInBackground --> onProgressUpdate --> onPostExecute
     */
    public class TestAsyncTask extends AsyncTask<Void, Integer, String> {
    
        /**
         * 通常用于一些初始化操作
         */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            // 在主线程(UI线程)
            // 进行各种初始化
        }
    
        /**
         * 核心方法,负责执行很耗时的异步任务工作。
         */
        @Override
        protected String doInBackground(Void... voids) {
            // 在子线程
            // 在onPreExecute方法执行后马上执行
    
            // 可调用publishProgress() 方法触发onProgressUpdate对UI进行操作
            // 比如传递后台任务的进度值,倒计时,下载进度....等
            publishProgress(10);
    
            return "String";
        }
    
        /**
         * 负责回主线程进行UI交互,比如实时刷新显示进度条数据等
         * 在doInBackground方法中调用publishProgress方法则触发该方法
         */
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            // 在主线程(UI线程)
            // 在这里处理UI更新等
        }
    
        /**
         * 接收线程任务的执行结果,将执行结果进行回调到主线程
         */
        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            // 在主线程(UI线程)
            // 异步任务doInBackground执行完毕会自动执行该方法
            // 这里onPostExecute方法的参数,和doInBackground的返回值类型必须保持一致
    
        }
    
        /**
         * 取消异步任务时触发该方法
         */
        @Override
        protected void onCancelled(String s) {
            super.onCancelled(s);
            // 在主线程(UI线程)
            // 取消异步任务时触发该方法
    
        }
    }
    
    

    三、如何使用

    1、在doInBackground方法中实现异步任务。
    2、建AsyncTask子类的实例对象
    3、手动调用execute( )从而执行异步线程任务。

    • Task的实例必须在主线程中创建;
    • execute()方法必须在主线程中调用;
    • 不要手动的调用onPreExecute()、onPostExecute(Result)、doInBackground(Param…)、onProgressUpdate(Progress…)这几个方法;
    • 每个实例Task只能被执行一次,否则多次调用时将会出现异常。所以要进行判断。

    四、AsyncTask使用示例(延时线程来模拟文件下载的过程):

    布局文件:activity.xml:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
        xmlns:tools="http://schemas.android.com/tools"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent"  
        android:orientation="vertical"  
        tools:context=".MyActivity">  
        <TextView  
            android:id="@+id/txttitle"  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content" />  
        <!--设置一个进度条,并且设置为水平方向-->  
        <ProgressBar  
            android:layout_width="fill_parent"  
            android:layout_height="wrap_content"  
            android:id="@+id/pgbar"  
            style="?android:attr/progressBarStyleHorizontal"/>  
        <Button  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:id="@+id/btnupdate"  
            android:text="更新progressBar"/>  
    </LinearLayout> 
    
    

    定义一个延时操作,用于模拟下载:

    public class DelayOperator {  
        //延时操作,用来模拟下载  
        public void delay()  
        {  
            try {  
                Thread.sleep(1000);  
            }catch (InterruptedException e){  
                e.printStackTrace();;  
            }  
        }  
    }
    
    

    自定义AsyncTask:

    public class MyAsyncTask extends AsyncTask<Integer,Integer,String>  {  
        private TextView txt;  
        private ProgressBar pgbar;  
      
        public MyAsyncTask(TextView txt,ProgressBar pgbar)  {  
            super();  
            this.txt = txt;  
            this.pgbar = pgbar;  
        }  
    
        //该方法运行在UI线程中,可对UI控件进行设置  
        @Override  
        protected void onPreExecute() {  
            txt.setText("开始执行异步线程~");  
        }  
      
        //该方法不运行在UI线程中,主要用于异步操作,通过调用publishProgress()方法  
        //触发onProgressUpdate对UI进行操作  
        @Override  
        protected String doInBackground(Integer... params) {  
            DelayOperator dop = new DelayOperator();  
            int i = 0;  
            for (i = 10;i <= 100;i+=10)    {  
                dop.delay();  
                publishProgress(i);  
            }  
            return  i + params[0].intValue() + "";  
        }  
    
        //在doBackground方法中,每次调用publishProgress方法都会触发该方法  
        //运行在UI线程中,可对UI控件进行操作  
        @Override  
        protected void onProgressUpdate(Integer... values) {  
            int value = values[0];  
            pgbar.setProgress(value);  
        }  
        /**
         * 取消异步任务时触发该方法
         */
        @Override
        protected void onCancelled(String s) {
            super.onCancelled(s);
            // 在主线程(UI线程)
            // 取消异步任务时触发该方法
    
        }
    }
    
    

    MainActivity.java:

    public class MyActivity extends ActionBarActivity {  
      
        private TextView txttitle;  
        private ProgressBar pgbar;  
        private Button btnupdate;  
      
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
            txttitle = (TextView)findViewById(R.id.txttitle);  
            pgbar = (ProgressBar)findViewById(R.id.pgbar);  
            btnupdate = (Button)findViewById(R.id.btnupdate);  
            btnupdate.setOnClickListener(new View.OnClickListener() {  
                @Override  
                public void onClick(View v) {  
                    MyAsyncTask myTask = new MyAsyncTask(txttitle,pgbar);  
                    myTask.execute(1000);  
                }  
            });  
        }  
    } 
    
    

    相关文章

      网友评论

          本文标题:Android-AsyncTask异步任务、

          本文链接:https://www.haomeiwen.com/subject/jmlquhtx.html