(一) 进程
四大组件元素的清单条目(activity, service, receiver, provider)均支持android:process属性,此属性可以指定该组件应在哪个进程运行。
可以设置 android:process,使不同应用的组件在相同的进程中运行,但前提是这些应用共享相同的 Linux 用户 ID 并使用相同的证书进行签署。
此外, application元素还支持 android:process 属性,以设置适用于所有组件的默认值。
进程生命周期
Android 系统将尽量长时间地保持应用进程,但为了新建进程或运行更重要的进程,最终需要清除旧进程来回收内存。
重要性层次结构一共有 5 级。以下列表按照重要程度列出了各类进程:
1 前台进程
如果一个进程满足以下任一条件,即视为前台进程:
- 托管用户正在交互的Activity(已调用Activity的onResume()方法)
- 托管某个Service,此Service绑定到用户正在交互的Activity
- 托管正在“前台”运行的Service(服务已调用startForeground())
- 托管正在执行一个生命周期回调的Service(onCreate(),onStart(),或 onDestory())
- 托管正执行其onReceive()方法的BroadcastReceiver
2 可见进程
没有任何前台组件、但仍会影响用户在屏幕上所见内容的进程。
如果一个进程满足以下任一条件,即视为可见进程:
- 托管不在前台、但仍对用户可见的 Activity(已调用其 onPause() 方法)。例如,如果前台 Activity 启动了一个对话框,允许在其后显示上一 Activity,则有可能会发生这种情况 。
- 托管绑定到可见(或前台)Activity 的 Service
3 服务进程
正在运行已使用 startService() 方法启动的服务且不属于上述两个更高类别进程的进程。
尽管服务进程与用户所见内容没有直接关联,但是它们通常在执行一些用户关心的操作(例如,在后台播放音乐或从网络下载数据)。
4 后台进程
包含目前对用户不可见的 Activity 的进程(已调用 Activity 的 onStop() 方法)。
通常会有很多后台进程在运行,因此它们会保存在 LRU (最近最少使用 Least Recently Used)列表中,以确保包含用户最近查看的 Activity 的进程最后一个被终止。
5 空进程
不含任何活动应用组件的进程。保留这种进程的的唯一目的是用作缓存,以缩短下次在其中运行组件所需的启动时间。
(二)线程
应用启动时,系统会为应用创建一个名为“主线程”的执行线程。
此线程非常重要,因为它负责将事件分派给相应的用户界面小工具,其中包括绘图事件。
它也是应用与 Android UI 工具包组件(来自 android.widget 和 android.view 软件包的组件)进行交互的线程。
因此,主线程有时也称为 UI 线程。
Android UI 工具包并非线程安全工具包。因此,您不得通过工作线程操纵 UI,而只能通过 UI 线程操纵用户界面。因此,Android 的单线程模式必须遵守两条规则:
1 不要阻塞 UI 线程
(如果 UI 线程被阻塞超过几秒钟时间(目前大约是 5 秒钟),用户就会看到一个让人厌烦的“应用无响应”(ANR) 对话框)
2 不要在 UI 线程之外访问 Android UI 工具包
Android 提供了几种途径来从其他线程访问 UI 线程。以下列出了几种有用的方法:
- Activity.runOnUiThread(Runnable)
- View.post(Runnable)
- View.postDelayed(Runnable, long)
随着操作日趋复杂,这类代码也会变得复杂且难以维护。
要通过工作线程处理更复杂的交互,可以考虑在工作线程中使用 Handler 处理来自 UI 线程的消息。
当然,最好的解决方案或许是扩展 AsyncTask 类,此类简化了与 UI 进行交互所需执行的工作线程任务。
(三)Demo:
功能:点击button,使用AsyncTask类下载图片并使用imageview显示出来。
public class AsyntaskActivity extends Activity {
private final static String mTag = "AsyntaskActivity";
Button button1;
public ImageView textImage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_asyntask);
button1 = (Button)findViewById(R.id.asyntask_load);
button1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
new DownloadImageTask().execute("https://img-my.csdn.net/uploads/avatar/4/D/E/1_ericyue83.jpg");
}
});
textImage = (ImageView) findViewById(R.id.asyntask_imageView);
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
@Override
protected Bitmap doInBackground(String... urls) {
try {
return loadImageFromNetwork(urls[0]);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
private Bitmap loadImageFromNetwork(String string) throws IOException {
URL url = new URL(string);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
if(connection.getResponseCode() != HttpURLConnection.HTTP_OK){
return null;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
InputStream in = connection.getInputStream();
int bytesRead = 0;
byte[] buffer = new byte[1024];
while((bytesRead = in.read(buffer))>0){
out.write(buffer, 0, bytesRead);;
}
out.close();
byte[] outBytes = out.toByteArray();
return BitmapFactory.decodeByteArray(outBytes, 0, outBytes.length);
}
@Override
protected void onPostExecute(Bitmap result) {
textImage.setImageBitmap(result);
}
}
(四)Reference:
http://developer.android.com/intl/zh-cn/guide/components/processes-and-threads.html