0%

Android Thread

安卓线程与进程

这个安卓的进程其实我感觉就是一个Activity就可以自己来一个进程,在我们的AndroidManifest.xml这个文件中我们可以通过:
android:process="XXX"来指定我们的进程,是否要新的一个进程,这个默认就是我们的包名。

进程优先级

因为安卓是手机的操作系统,内存少一些,所以他有个自动杀死进程的一个机制,主要是用来杀死一些不太重要的进程,在我们内存不太充足的条件下。

  • 前台进程
  • 可见进程
  • 服务进程
  • 后台进程
  • 空进程

这个看名字基本就能明白,可见进程就是我们虽然不可见,其实也就是不能进行UI的操作了,比如说我们的一个程序,打的第二个Activity的时候他就变成了可见进程,空进程就是我们退出的进程,后台进程是我们虽然回到了主窗口,但是我们没有退出。
安卓会从下到上依次删除进程。

handle消息处理机制

这个东西就和Windows下面的消息循环很像,主要应对的是,子线程中我们不能对主线程的UI进行操作。

1
2
3
4
5
6
7
8
9
10
try {
Thread.sleep(2*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

String str = "执行完毕";
Message msg = new Message();
msg.obj = str;
handler.sendMessage(msg);

run方法中写这个就代码,这个handler使我们自写的。

1
2
3
4
5
6
7
8
9
private Handler handler = new Handler()
{
public void handleMessage(Message msg)
{
String str = (String) msg.obj;
tv_tx.setText(str);
Log.d("wker", (Looper.getMainLooper()==Looper.myLooper())+"");
};
};

很简单,我们重写这个handleMessage这个方法,这个对象是在我们的主线程的,所以可以操作UI,当我们调用sendMessage这个方法的时候我们就会接受到这个消息,我们可以检查下是不是在主线程,确实是在主线程,输出为true。
当然我们还有一种就是延迟执行,意思就是隔几秒才进行UI的操作:

1
2
3
4
5
6
7
8
handler.postDelayed(new Runnable() {

@Override
public void run() {
tv_tx.setText("test");
Log.d("wker", "test");
}
},10000);

这个就是所在10s之后执行,测试中发现同样可以操作UI。
但是要注意的是,我们并不能在子线程中直接创建这个Handler对象,因为我们主线程中拥有Looper对象,而子线程中没有,所以我们先要给他准备一个,具体的操作代码:

1
2
3
4
Looper.prepare();//Looper初始化
//Handler初始化 需要注意, Handler初始化传入Looper对象是子线程中缓存的Looper对象
Handler mHandler = new Handler(Looper.myLooper());
Looper.loop();//死循环

但是我们下面的代码就没办法执行了,因为那个loop就是在哪里一直死循环了,其实主线程的UI操作也就是这样死循环,但是为什么不会出现ANR的这个异常,这个是因为Linux的一些原因。

AsyncTask

这个就是很方便很好地一个东西,用来新建线程并且可以操作UI,我们需要继承这个类,然后重写一些方法,他是一个泛型,又是那个需要传入的参数,第一个是我们后台运行所要接受的参数类型,第二个是我们进行数据更新的时候,所要传入的参数类型,第三个是我们后台运行的返回值的参数(传递给onPostExecute方法的)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class MyAsy extends AsyncTask<String, String, String>
{

@Override
protected void onPreExecute() {
Log.d("wker", "开始执行");
super.onPreExecute();
}


@Override
protected String doInBackground(String... params) {
try {
for (int i = 0; i < 3; i++) {
String string = params[0];
publishProgress(i+"");
Thread.sleep(2000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return params[0]+"---"+params.length;
}

@Override
protected void onProgressUpdate(String... values) {
tv_tx.setText(values[0]);
super.onProgressUpdate(values);
}

@Override
protected void onPostExecute(String result) {

tv_tx.setText(result);
super.onPostExecute(result);
}

}

一般写在内部类中,好调用,当我们执行对象的execute方法的时候,我们先执行onPreExecute方法,也就是一些准备操作,在主线程中,比如我们的加载对话框出现,然后执行doInBackground方法,是在子线程中执行,传进来的参数也就是我们execute的时候传进来的可变长度的参数,返回值是提供给onPostExecute方法(这个方法运行在主线程中)的,在我们加载的过程中可能会报告进度给UI,onProgressUpdate这个方法就是用来接收进度的,在主线程中,用来操作进度条的。

executedoInBackground的参数以及: 是第一个泛型
onProgressUpdate:这个的参数是第二个泛型
onPostExecute的参数和doInBackground的返回值是第三个泛型

AsyncTask这个类内部有一个静态的线程池,是用来要用到线程的时候拿出线程用的。

在主线程中调用:

1
2
MyAsy ma = new MyAsy();
ma.execute("cecece");

这样我们就可以进行子线程中操作了。

遗留线程处理,安卓当中主线程结束,子线程还不结束,这个和Windows中有点区别,所以我们需要主线程结束之后子线程也要结束,我们可以设置一个标志位,在主线程销毁的时候,将这个标志位设置为false,子线程检查到是false的时候,就结束任务就可以了。