android 之多线程详解

Android 中进程的生命周期

<1>前台进程(Foreground process):正在运行着和用户交互的程序的进程

<2>可见进程(visible process):运行着处于可见状态组件的进程

<3>服务进程(Service process):运行着使用startService()方法的服务同时没有变为更两个级别的进程

<4>后台进程(Background process):运行着处于后台组件的进程,执行了Activity的onStop()方法后的进程

<5>空进程(Empty Process):不包含任何活动组建的进程,它们的存在是为了缓存的目的,能够加速重新启动当前程序的速度。




UI线程(主线程)模型的两条规则:

1.不要阻塞UI线程,否则超过5s会出现ANR(Applocation Not Responding)错误的危险。

2.不要在非UI线程中更新UI,否则直接报错。




解决UI线程模型两条规则之间的矛盾,提供了三种方式

A.把主线程请到子线程的家里面,通过调用Activity的runOnUiThread(new Runnable(){  重写run方法 }} );   

   或者是view.post(new Runnable()){ 重写run方法 }} );

1.Activity.runOnUiThread(Runnable)

2.View.post(Runnable)

3.View.postDelayed(Runnable,long)

B.当子线程有更新UI需要的时候,当需要更新数据封装到消息对象中并反送给主线程进行更新UI(Handler机制)  以后补充!

C.使用Google提供的AsyncTask(异步)解决。



    AsyncTask的特点:

    掌握如何构建AsyncTask子类:

    掌握AsyncTask<String,Integer,String>三个泛型参数的说明:

<1>第一个参数:指定当我们启动异步任务(execute()方法实参的数据类型)时传递给doInBackground(String...parms)

      方法的形参的数据类型加上。。。

<2>第二个参数:指定对外报告进度时调用方法publish Progress()中实参的数据类型。。。也是 

          onProgressUpdate(Integer...values)方法形参的数据类型。。。

<3>第三个参数:指定doInBackground(String...parms)方法返回值的数据类型,也是onPostExcute(String s)方法形参的数据类型


package com.hsj.example.asynctaskdemo01;

import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

import java.util.Arrays;


/**
 * https://www.baidu.com/img/bd_logo1.png?qua=high&where=super
 */
public class MainActivity_bak04 extends AppCompatActivity {

    private TextView textView_info;

    private ProgressDialog progressDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        this.textView_info= (TextView) this.findViewById(R.id.textView_info);

        //实例化对话框对象
        this.progressDialog=new ProgressDialog(this);
        this.progressDialog.setMax(100);
        //将对话框样式设置成水平进度对话框
        this.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);




        //当执行execute()方法时会自动调用doInBackground(Void... params)
        new MyAsyncTask().execute("http://www.baidu.com","http://www.163.com");
       // new MyAsyncTask().execute("http://www.baidu.com","http://www.163.com");


        //MyAsyncTask myAsyncTask=new MyAsyncTask();
        //myAsyncTask.execute("http://www.baidu.com","http://www.163.com");
        /*异步任务不能多次启动,否则报异常:Cannot execute task: the task is already running*/
        //myAsyncTask.execute("http://www.baidu.com","http://www.163.com");

    }

    /**
     * AsyncTask<String,Integer,String>三个泛型参数说明:
     * 第一个参数:指定当我们启动异步任务(execute()方法实参的数据类型)时传递给doInBackground(String... params)方法的形参的数据类型加上...
     * 第二个参数:指定对外报告进度时调用方法publishProgress()中实参的数据类型....,也是onProgressUpdate(Integer... values)方法形参的数据类型...
     * 第三个参数:指定doInBackground(String... params)方法返回值的数据类型,也是onPostExecute(String s)方法形参的数据类型
     *
     */
   private final  class MyAsyncTask extends AsyncTask<String,Integer,String>{

        @Override
        protected void onPreExecute() {
            //设置进度对话框的提示消息
            progressDialog.setMessage("开始下载网络图片......");
            //显示进度对话框
            progressDialog.show();
            System.out.println("===onPreExecute()===");
        }

        @Override
       protected String doInBackground(String... params) {
           System.out.println("===doInBackground(String... params="+params+")==");
           System.out.println("params="+ Arrays.toString(params));

            //publishProgress(10,20,30);//报告进度的值会传递给onProgressUpdate(Integer... values)方法的形参values


            for(int i=0;i<100;i++){
                publishProgress(i);



                if(i==50){
                    System.out.println("===用户取消了下载====");
                    //取消执行耗时操作
                    this.cancel(true);

                }
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            return "网络下载数据完毕";
       }

        @Override
        protected void onProgressUpdate(Integer... values) {

            progressDialog.setProgress(values[0]);
            System.out.println("===onProgressUpdate(Integer... values="+Arrays.toString(values)+")===");

        }

        /**
         * 当用户执行了取消异步任务的操作后自动调用的方法,此时就不再调用onPostExecute(String s)
         * 当前方法也是运行在主线程中
         */
        @Override
        protected void onCancelled() {
            //销毁进度对话框
            progressDialog.dismiss();
             String threadName=Thread.currentThread().getName();
            System.out.println("===onCancelled().threadName="+threadName);
        }

        /**
         * 当正常执行完毕异步任务中的doInBackground()方法后指定调用的方法
         * @param s
         */
        @Override
        protected void onPostExecute(String s) {
            //销毁进度对话框
             progressDialog.dismiss();
            System.out.println("===onPostExecute(String s="+s+")====");
        }
    }


}




示例代码

package com.hsj.example.asynctaskdemo01;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;


public class MainActivity extends AppCompatActivity {

    private TextView textView_info;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        this.textView_info= (TextView) this.findViewById(R.id.textView_info);
    }

    /**

     * android 单线程模型的内容:
     *   1.不要阻塞UI线程,因为超过5秒后可能会出现ANR(Application Not Response) 应用程序无响应错误
     *   2.不要在子线程中直接更新UI,否则会直接报错
     *
     *
     * 为了解决android单线程模型的问题,我们提供了三种解决方案:
     *  A:把主线程请到子线程的家里来
     *      1. Activity.runOnUiThread(Runnable)
     *
            2. View.post(Runnable)
            3. View.postDelayed(Runnable, long)
     *
     *  B:使用Handler机制(当子线程有更新UI的意愿时,把需要更新的数据封装成消息传递到主线程中在更新UI),将在第十八章详解
     *
     *  C:使用异步任务解决,这章的重点.
     *
     * @param view
     */
    public void click(View view){



        /*
        在java 中开启子线程有两种方式:
        A:继承Thread 类
        B:实现Runnable 接口
         */

        new  Thread(){
            @Override
            public void run() {
                String threadName=Thread.currentThread().getName();
                System.out.println("threadName="+threadName);

                //模拟耗时操作,比如网络下载
               /* try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }*/

               final  String info="你点我的后果看到了吗?";

                /*//在子线程中开辟一块主线程的执行区域,方式一:
                runOnUiThread(new Runnable() {
                    *//**
                 * run()方法就运行在主线程中了
                 *//*
                    @Override
                    public void run() {
                        String myName=Thread.currentThread().getName();
                        System.out.println("Runnable.myName="+myName);
                        //更新UI,在内部类中访问外部类的局部变量则需要将局部变量变成常量
                        textView_info.setText(info);
                    }
                });*/


                /*//方式二:
                textView_info.post(new Runnable() {
                    @Override
                    public void run() {
                        String myName=Thread.currentThread().getName();
                        System.out.println("Runnable.myName="+myName);
                        //更新UI,在内部类中访问外部类的局部变量则需要将局部变量变成常量
                        textView_info.setText(info);
                    }
                });*/


                //方式三:postDelayed(runnable,long):延迟long 毫秒后执行run()方法
                textView_info.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        String myName=Thread.currentThread().getName();
                        System.out.println("Runnable.myName="+myName);
                        //更新UI,在内部类中访问外部类的局部变量则需要将局部变量变成常量
                        textView_info.setText(info);
                    }
                },2000);


            }
        }.start();

    }
}

异步任务的实例:

点击打开链接


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值