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();
}
}
异步任务的实例: