本文主要是介绍android中线程和进程工作原理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Android中默认情况下,同一应用中的所有组件运行在同一个进程和线程中。你的应用中没有其他组件在运行,那么Android将会给你开启一个新的Linux的进程,然后运行一个main线程来运行你的应用。如果你应用中已经有其他组件在运行,你再开启你的应用时,开启的应用会使用之前正在运行的线程和进程。
下面介绍一个应用中的线程和进程是如何工作的。
一、进程。
默认情况下,同一应用程序的所有组件运行在相同的进程,大多数应用程序不应该改变这种情况。然而,如果你发现你需要控制某一组件属于同一进程,你可以在manifest文件中进行实现。
在<activity>这些标签中都支持Android:process属性这样用户可以指定某些组件运行在哪一个具体的进程上。具有相同 的Linux 用户ID并且在相同的证书下开发的不同应用中的组件可以运行在相同的进程中。通过上述的熟悉就可以实现。
<application>也支持该属性,给应用设置默认的运行的进程。
1.进程的声明周期。当系统资源紧张或者内存使用量较高的时候,Android会选取当前的一些进程予以关闭,进而提高你的设备的运行性能。Android中主要有5中级别的进程。
1)前台进程。下面五种情况说明是前台进程。在一个给定的时间内前台进程的数量是很少的,其基本不会被系统关闭。
(1)用户正在与其交互(调用onResume方法重新开始)。
(2)一个绑定到Activity的Service,并且用户正在于其进行交互。
(3)一个Service但是调用了startForeground方法。
(4)一个调用onCreate onStart onDestory的Service回调方法。
(5)一个Broadcast Receiver正在调用onReceive方法。
2)可见进程。
不是前台进程但是对用户当前可见的界面还是有影响的进程。
(1)一个Activity调用了onPause方法。
(2)一个绑定了可见或者前台进程的Service。
3)服务进程。
调用了startService的Service,但是没有绑定到可见和前台进程上。当内存过低的时候,服务可能会被停掉来保证可见和前台进程的正常运行。
4)后台进程。
对用户当前没有任何的响应,可以随时关闭的进程。系统中会存在大量的后台进程,并且使用LRU算法对这些进程进行维护来提高系统的运行效率。当Activity中调用onstop方法,进程就成为了后台进程。
5)空进程。
空进程不会持有任何活动应用的组件,空进程存在的目的是为了缓存,以提高下次组件启动的速度。操作系统会对进程的缓存和内核内部的缓存进行衡量,是系统运行最优。
上述,优先级从高到底,主要是按照进程的重要程度进行分类的。
二、线程。
当一个应用开启的时候,操作系统会为应用创建一个main线程来运行应用。这个线程非常重要,其负责管理将所有的事件派发到适当的用户接口工具中,包括drawable事件。该线程并负责与Android UI工具包中的组件进行交互,所以该线程又被称为UI线程。同一个组件的实例将会运行在相同的线程中,运行在系统进程中的组件都是由同一个UI线程实例化的。故所有的响应系统的回调函数如onKeyDown都会运行在进程中的UI线程中。UI线程还需要负责和UI工具包进行交互。
这里以点击Button从新绘制当前View为例进行说明;
当用户点击一次Button按钮时,你应用的UI线程会将你的点击事件派发到widget,widget反过来会设置按压状态然后发送一个invalidate事件到事件队列,你的UI线程随后将从事件队列中取出事件,然后通知widget需要重新绘制当前View。
当你的应用要执行用户交互敏感的操作的时候,如网络访问,数据库查询,其操作可能会很耗时,很可以能导致ANR,这时会给用户很差的使用体验。并且UI工具包是不安全的,你需要使用worker线程对UI进行维护,并且你需要维护其和UI线程交互的所有操作。下面有两条建议:
(1)不要阻塞UI线程。否则事件将不会派发,然后就出现了ANR。
(2)不要再UI线程之外访问AndroidUI工具包。
故,关键不要阻塞UI线程。对于耗时的线程可以放到其他的线程中进行处理。如下面的操作
public void onClick(View v) {new Thread(new Runnable() {public void run() {Bitmap b = loadImageFromNetwork("http://example.com/image.png");mImageView.setImageBitmap(b);}}).start(); }但是,这违背了第(2)条准则。Android提供了下面的三种方式来解决上述问题。
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
public void onClick(View v) {new Thread(new Runnable() {public void run() {final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");mImageView.post(new Runnable() {public void run() {mImageView.setImageBitmap(bitmap);}});}}).start(); }上述代码完成了网络请求操作和主线程的分离,并且将对UI工具包的访问又放到了main线程中进行。
但是,随着操作的复杂上述代码是不太好维护的。可以在worker Thread中使用Handler对来自UI线程中的消息进行派发。但是,或许最好的方式就是进程AsynTask类,能够简化Worker Thread和UI之间的交互。
AsynTask的使用方式:
public void onClick(View v) {new DownloadImageTask().execute("http://example.com/image.png"); }private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {/** The system calls this to perform work in a worker thread and* delivers it the parameters given to AsyncTask.execute() */protected Bitmap doInBackground(String... urls) {return loadImageFromNetwork(urls[0]);}/** The system calls this to perform work in the UI thread and delivers* the result from doInBackground() */protected void onPostExecute(Bitmap result) {mImageView.setImageBitmap(result);} }使用上述方式,你的代码的安全性就比较高了,因为其将两个线程分离开。
AsynTask使用综述:
1)可以使用泛型来指定参数类型,进度值和最终值。
2)doInBackground会在Worker Thread中自动调用。而onPostExecute onPreExecute onProgessUpdate会自动的在UI线程中调用。
3)doInbackgroudn的返回值会发送到哦你PostExecute方法。
4)你可以在doInbackground方法中任意的调用publishProgess方法来执行UI线程中的onProgessUdapte方法。
3)你可以在任何线程中,在任何时间取消该任务。
但是如果在运行期间发生了,运行时配置改变的时候,你的Worker Thread可能会被中断的。
IPC简介
Android中提供了一种远程过程调用(RPC)的机制用来处理IPC过程。RPC机制中,当一个Activity或者应用程序的其他的组件调用了RPC中的方法,该方法会在别的进程(远端进程)中执行然后将返回值返回给调用者。这就需要将方法调用和数据分解到一个操作系统可以理解的水平,并且能够将其从本地进程和地址空间中传递到远程的进程和地址空间,然后再重新组装和定制调用。返回值会以相反的方向传递返回给本地。Android中已经提供了实现IPC的所有的代码,因此程序员只需要关注和实现RPC编程接口。
如果想要使用IPC,那么你的应用必须要绑定到Service上,即调用bi
翻译自:Android官方文档。
这篇关于android中线程和进程工作原理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!