Processes and Threads 进程和线程,面试题bug的生命周期

This might occur, for example, if the foreground activity started a dialog, which allows the previous activity to be seen behind it.

比如,这种情况可以发生在,一个前台活动启动了一个对话框,这允许先前的活动在对话框的下面可以看到。

It hosts a Service that’s bound to a visible (or foreground) activity.

它持有一个服务,该服务邦定到一个可见的或者一个前台活动

A visible process is considered extremely important and will not be killed unless doing so is required to keep all foreground processes running.

可视进程被认为是非常重要的,并不会被杀掉,除非为了保持所有前台运行的进程而必须要杀掉它。

Service process服务进程

A process that is running a service that has been started with the startService() method and does not fall into either of the two higher categories.

一个进程正在运行一个服务,并且该服务已启动了startService()方法,也不是任一更高级别进程

Although service processes are not directly tied to anything the user sees, they are generally doing things that the user cares about

(such as playing music in the background or downloading data on the network),

so the system keeps them running unless there’s not enough memory to retain them along with all foreground and visible processes.

虽然服务进程与用户所见不直接的紧密关联,但它们通常处理用户所关心的事情(比如在后台播放音乐或从网上下载数据),所以系统保持它们运行,除没有足够的空间维持它们与所有

的前台和可见进程。

Background process后台进程

A process holding an activity that’s not currently visible to the user (the activity’s onStop() method has been called).

进程持有一个当前对用户不可见的活动(该活动的onStop()方法已经调用)

These processes have no direct impact on the user experience, and the system can kill them at any time to reclaim memory for a foreground,

visible, or service process.

这些进程对不直接影响用户的体验,当为前台进程,可见进程和服务进程回收内存时,系统随时可以杀掉它们。

Usually there are many background processes running, so they are kept in an LRU (least recently used) list to ensure that the process with the activity

that was most recently seen by the user is the last to be killed.

通常会有许多后台进程在运行,所以它们被保存在一个LRU(最近使用列表)列表中,以确保用户最近看到的活动的进程最后被杀掉。

If an activity implements its lifecycle methods correctly, and saves its current state, killing its process will not have a visible effect on the user experience,

because when the user navigates back to the activity, the activity restores all of its visible state.

如果一个活动正确的实现了它的生命周期方法,并且保存它的当前状态,杀掉它的进程不会对用户休验有明显的影响,因为当用户导航返回时,活动将恢复所有它的可见状态

See the Activities document for information about saving and restoring state.关于保存和恢复活动的状态,请看Activities文档

Empty process空进程

A process that doesn’t hold any active application components. 一个进程不捅有任何应用的组件

The only reason to keep this kind of process alive is for caching purposes, to improve startup time the next time a component needs to run in it.

保持此进程活着的唯一原因是用缓冲,以提高下次一个组件要在它里面运行时的启动速度.

The system often kills these processes in order to balance overall system resources between process caches and the underlying kernel caches.

为了平衡所有系统资源及进程缓冲和底层内核缓冲,系统经常要杀掉这些进程.

Android ranks a process at the highest level it can, based upon the importance of the components currently active in the process.

For example, if a process hosts a service and a visible activity, the process is ranked as a visible process, not a service process.

Android系统根据进程当前活动的组件的重要性,给一个进程排一个它能到达的最高级别.比如,如果一个进程持有一个服务和可见活动,该进程将被按排成一个可见进程,而不是一个服务进程.

In addition, a process’s ranking might be increased because other processes are dependent on it—

a process that is serving another process can never be ranked lower than the process it is serving.

另外,一个进程的排序可能会因为其他依赖于它的进程而提高—一个正在服务其他的进程的进程,它的排序不可能比它所服务的进程的排序低.

For example, if a content provider in process A is serving a client in process B, or if a service in process A is bound to a component in process B,

process A is always considered at least as important as process B.

比如,一个在A进程的内容提供者,正在服务于进程B的客户端,或者一个进程A的服务,邦定到了一个进程B的组件.进程A总是被认为至少与进程B一样重要.

Because a process running a service is ranked higher than a process with background activities,

an activity that initiates a long-running operation might do well to start a service for that operation,

rather than simply create a worker thread—particularly if the operation will likely outlast the activity.

由于运行一个服务的进程比一个带有后台活动的进程级别更高,所以一个打算长期运行的操作的活动,最好为那个操作启动一个服务,而不是仅仅简单的为他

创建一个工作线程——特别是该操作将可能比活动运行得更长久时。

For example, an activity that’s uploading a picture to a web site should start a service to perform the upload

so that the upload can continue in the background even if the user leaves the activity.

比如,一个要上传图片到网上的活动,应该启动一个服务来执行上传,以便即使用户离开了活动,上传动作仍可以在后台继续。

Using a service guarantees that the operation will have at least “service process” priority, regardless of what happens to the activity.

使用一个服务,可以保证该操作将必至少捅有"服务进程"的优先级,而不论活动发生了什么。

This is the same reason that broadcast receivers should employ services rather than simply put time-consuming operations in a thread.

同样一个广播接收器应该顾用一个服务,而不是简单的在一个线程中放一个耗时的操作。

Threads 线程

When an application is launched, the system creates a thread of execution for the application, called “main.”

当应用被运行后,系统为它创建一个执行线程,叫做"主线程main"

This thread is very important because it is in charge of dispatching events to the appropriate user interface widgets, including drawing events.

这个线程非常重要,因为它负责分发事件给相应的用户界面部件,包括绘画事件。

It is also the thread in which your application interacts with components from the Android UI toolkit (components from the android.widget and android.view packages).

As such, the main thread is also sometimes called the UI thread.

它也是应用中与Android UI工具集(android.widget和android.view包的组件)交互的线程,也因此,该主线程有时叫做UI线程

The system does not create a separate thread for each instance of a component.

系系不会为每个组件的实例,创建一个独立的线程

All components that run in the same process are instantiated in the UI thread, and system calls to each component are dispatched from that thread.

所以运行在同一个进程中的组件被实例化到 UI线程中,并且系统从该线程分发对每个组件的调用.

Consequently, methods that respond to system callbacks (such as onKeyDown() to report user actions or a lifecycle callback method) always run in the UI thread of the process.

相应的,响应系统的回调方法(比如报告用户动作的onKeyDown()方法,或者生命周期回调方法)总是运行在进程的UI线程中.

For instance, when the user touches a button on the screen, your app’s UI thread dispatches the touch event to the widget,

which in turn sets its pressed state and posts an invalidate request to the event queue. The UI thread dequeues the request and notifies the widget that it should redraw itself.

比如,当用户在屏上触模一个按钮,你的应用的UI线程分发一个触模事件到 widget, widget依次设置它的按下状态,并且发送一个无效请求到事件队列。UI线程出列该请求,并且通知该widget应该重绘它自己.

When your app performs intensive work in response to user interaction, this single thread model can yield poor performance unless you implement your application properly.

当你的应用密集的响应用户的交互时,这种单线程模式只能屈服于低效的性能,除非你恰当的实现了你的应用。

Specifically, if everything is happening in the UI thread, performing long operations such as network access or database queries will block the whole UI.

特别是,如果每件事件都发生在UI线程,执行像网络访问的长期操作,或数据库查询将会阻塞整个UI.

When the thread is blocked, no events can be dispatched, including drawing events. From the user’s perspective, the application appears to hang.

当该线程被阻塞时,没有事件可以被分发,包括重绘事件。从用户的角度,应用表现为挂起。

Even worse, if the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with the infamous “application not responding” (ANR) dialog.

甚至更糟的情况是,如果UI线程被阻塞超过几秒(当前是5秒),将给用户显示一个著名的"应用无响应"对话框.

The user might then decide to quit your application and uninstall it if they are unhappy.

那么用户可以决定退出人的应用,并且如果他们不高兴的话,会卸载你的应用。

Additionally, the Andoid UI toolkit is not thread-safe. So, you must not manipulate your UI from a worker thread—you must do all manipulation to your user interface from the UI thread.

另外,Android UI工具集,不是线程安全的。所以,你不要从工作线程中篡改你的UI——而是在UI线程中,执行所有对用户界面的篡改。

Thus, there are simply two rules to Android’s single thread model:

因此,对于Android的单线程模式只有简单的两条规则:

Do not block the UI thread不要阻塞UI线程

Do not access the Android UI toolkit from outside the UI thread不要从UI线程之外访问Android的UI工具集

Worker threads工作线程

Because of the single thread model described above, it’s vital to the responsiveness of your application’s UI that you do not block the UI thread.

根据上述描述的单线程模式,不阻塞你的UI线程,对于你的应用的响应能力至关重要。

If you have operations to perform that are not instantaneous, you should make sure to do them in separate threads (“background” or “worker” threads).

如果你要执行的操作,不是瞬间完成的,你应该确保在一个独立的线程中执行这些操作(“后台”或"工作"线程)

For example, below is some code for a click listener that downloads an image from a separate thread and displays it in an ImageView:

比如,下面是一个click监听的一些代码,用于从一个独立的线程中下载一张图片并且在ImageView中显示:

public void onClick(View v) {

new Thread(new Runnable() {

public void run() {

Bitmap b = loadImageFromNetwork(“http://example.com/image.png”);

mImageView.setImageBitmap(b);

}

}).start();

}

At first, this seems to work fine, because it creates a new thread to handle the network operation. 首先,这似乎工作的很好,因为它创建了一个新的线程来处理网络的操作。

However, it violates the second rule of the single-threaded model: 但是,它违返了单线程模式的第二条规则

do not access the Android UI toolkit from outside the UI thread—this sample modifies the ImageView from the worker thread instead of the UI thread.

不能从UI线程之外访问Android UI 工具组件——这段代码从工作线程而不是UI线程,修改了ImageView。

This can result in undefined and unexpected behavior, which can be difficult and time-consuming to track down.

这将导致未定义的及意料之外的行为,这将是难以追踪

To fix this problem, Android offers several ways to access the UI thread from other threads. Here is a list of methods that can help:

为了解决这个问题,Android提供了几种方法从其他的线程中访问UI线程。下面列出了一些有所帮助的方法:

Activity.runOnUiThread(Runnable)

View.post(Runnable)

View.postDelayed(Runnable, long)

For example, you can fix the above code by using the View.post(Runnable) method:比如,你用View.post(Runnable)方法,解决上述问题

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();

}

Now this implementation is thread-safe: the network operation is done from a separate thread while the ImageView is manipulated from the UI thread.

现在,这个实现是线程安全的了:网络操作从一个单独的线程,同时ImageView在UI线程中操作。

However, as the complexity of the operation grows, this kind of code can get complicated and difficult to maintain.

但是,由于它的操作的复杂性,这种代码会变得复杂和难以维护。

To handle more complex interactions with a worker thread, you might consider using a Handler in your worker thread, to process messages delivered from the UI thread.

为了处理与工作线程复杂的交互,你可以考虑在你的工作线程中使用一个句柄,处理来自UI线程的消息。

Perhaps the best solution, though, is to extend the AsyncTask class, which simplifies the execution of worker thread tasks that need to interact with the UI.

不过,也许最佳的解决方法,是继承AsynTask类,它只是简单的执行需要与UI交互的工作线程任务。

Using AsyncTask 使用AsyncTask类

AsyncTask allows you to perform asynchronous work on your user interface.AsyncTask它允许你在用户界面执行异步操作

It performs the blocking operations in a worker thread and then publishes the results on the UI thread, without requiring you to handle threads and/or handlers yourself.

它在工作线程中执行阻塞操作,并且然后发送结果到UI线程,而不必你去处理线程或者(handlers yourself)

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

To use it, you must subclass AsyncTask and implement the doInBackground() callback method, which runs in a pool of background threads.

要使用它,你必须扩展AsyncTask并且实现它的doInBackground() 回调方法,它运行在后台线程池中。

To update your UI, you should implement onPostExecute(), which delivers the result from doInBackground() and runs in the UI thread, so you can safely update your UI.

为了更新你的UI,你应实现onPostExecute()方法,它传递来doInBackground()自方法的结果,并运行在UI线程,所以你可以安全的更新你的UI.

You can then run the task by calling execute() from the UI thread.

你可以在UI线程中,调用execute()方法来运行此任务。

For example, you can implement the previous example using AsyncTask this way:举例 ,你以用 AsyncTask类,这样来实现前面的例子:

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()

* 系统在工作线程中调用此方法,并将传给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()

* 系统在UI线程中调用此方法并传递来自doInBackground() 方法的结果

*

*/

protected void onPostExecute(Bitmap result) {

mImageView.setImageBitmap(result);

}’/

}

Now the UI is safe and the code is simpler, because it separates the work into the part that should be done on a worker thread

and the part that should be done on the UI thread.

现在UI是安全的,代码也更简单,因为它分隔了应该在工作线程做的部分与应该在UI线程中做的部分。

You should read the AsyncTask reference for a full understanding on how to use this class, but here is a quick overview of how it works:

你应该阅读AsyncTask的参考,以完全理解怎样使用这个类,下面只是它如何工作的简要说明:

You can specify the type of the parameters, the progress values, and the final value of the task, using generics

你可以指定参数的类型,进程值,和任务的最终值,使用通用值

The method doInBackground() executes automatically on a worker thread 方法doInBackground()自动在工作线程执行

onPreExecute(), onPostExecute(), and onProgressUpdate() are all invoked on the UI thread 方法onPreExecute(), onPostExecute(), 和 onProgressUpdate()在UI线程中调用

The value returned by doInBackground() is sent to onPostExecute()由doInBackground()方法返回的值发给onPostExecute()方法

You can call publishProgress() at anytime in doInBackground() to execute onProgressUpdate() on the UI thread

任何时刻,你可以在doInBackground()方法,调用publishProgress(),来执行UI线程的onProgressUpdate().

You can cancel the task at any time, from any thread你可以随时在任意线程取消任务.

Caution: Another problem you might encounter when using a worker thread is unexpected restarts in your activity due to a runtime configuration change

(such as when the user changes the screen orientation), which may destroy your worker thread. 注

注意:当使用工作线程时你可能会碰到另一个问题,就是由于配置的改变,在你的活动出现了意外的重启。

To see how you can persist your task during one of these restarts and how to properly cancel the task when the activity is destroyed,

see the source code for the Shelves sample application.

要明白在这些重新启动期间如何持续你的任务,和当活动被销毁时如何适当的取消该任务.看Shelves例子应用的原码

Thread-safe methods线程安全方法

In some situations, the methods you implement might be called from more than one thread, and therefore must be written to be thread-safe.

在某些情况,你实现的这些方法可能从多个线程终结,并且因此要写成线程安全的。

This is primarily true for methods that can be called remotely—such as methods in a bound service.

可以远程

When a call on a method implemented in an IBinder originates in the same process in which the IBinder is running, the method is executed in the caller’s thread.

当调用的IBinder实现的方法,是与IBinder在同一个进程运行时,这个方法在在调用者的线程中执行的。

However, when the call originates in another process, the method is executed in a thread chosen from a pool of threads

that the system maintains in the same process as the IBinder (it’s not executed in the UI thread of the process).

但是,当调用源于另一个进程,该方法将从线程池中选一个线程来执行,该线程是由系统维护的与IBinder相同的进程中.(它不在进程的UI线程中执行).

For example, whereas a service’s onBind() method would be called from the UI thread of the service’s process,

methods implemented in the object that onBind() returns (for example, a subclass that implements RPC methods) would be called from threads in the pool.

比如,服务的onBind() 方法,可能从服务的进程的UI线程调用,onBind()返回对象的实现方法(比如,实现RPC方法的子类),可能在线程池中调用.

Because a service can have more than one client, more than one pool thread can engage the same IBinder method at the same time.

由于服务可能有多个客户端,所以同一时刻多个池线程可以占用同一个IBinder方法.

IBinder methods must, therefore, be implemented to be thread-safe.

因此,IBinder方法的实现必须是线程安全的。

Similarly, a content provider can receive data requests that originate in other processes.

同样,一个内容提供者可以收到源于另一个进程的数据请求

Although the ContentResolver and ContentProvider classes hide the details of how the interprocess communication is managed,

ContentProvider methods that respond to those requests—the methods query(), insert(), delete(), update(),

and getType()—are called from a pool of threads in the content provider’s process, not the UI thread for the process.

虽然,内容解释者和内容提供者类,隐藏了怎样管理进程间通信的的细节,但响应这些请求的内容提供者方法-query(), insert(), delete(), update(), getType()

都是从内容提供者的进程中的线程池调用,而不是从进程的UI线程调用

Because these methods might be called from any number of threads at the same time, they too must be implemented to be thread-safe.

因为这些方法可能同时由多个线程调用,它们的实现也必须是线程安全的.

Interprocess Communication进程间通信

Android offers a mechanism for interprocess communication (IPC) using remote procedure calls (RPCs),

in which a method is called by an activity or other application component, but executed remotely (in another process),with any result returned back to the caller.

Android使用远程过程调用(RPCs),做为进程间通信的机制.在这个机制中,活动或者其他的应用组件调用一个方法,但在远程执行(在其他进程),将结果返回给调用者.

This entails decomposing a method call and its data to a level the operating system can understand,

transmitting it from the local process and address space to the remote process and address space,

then reassembling and reenacting the call there.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值