例如,当用户触摸屏幕上的按钮时,应用的 UI 线程会将触摸事件分派给小部件,而小部件反过来又设置其按下状态,并将失效请求发布到事件队列中。 UI 线程从队列中取消该请求并通知小部件应该重绘自身
如果 UI 线程需要处理所有任务,则执行耗时很长的操作将会阻塞整个 UI。 一旦线程被阻塞,将无法分派任何事件,包括绘图事件。如果 UI 线程被阻塞超过特定时间(目前大约是 5 秒钟),用户就会看到一个显示“应用无响应”(ANR) 文本的对话框
此外,Android UI 工具包并非线程安全工具包。因此不能通过工作线程操纵 UI,而只能通过 UI 线程操纵用户界面。 因此,Android 的单线程模式必须遵守两条规则:
- 不要阻塞 UI 线程
- 不要在 UI 线程之外访问 Android UI 工具包
四、工作线程
根据上述单线程模式,要保证应用 UI 的响应能力,关键是不能阻塞 UI 线程。如果执行的操作不能很快完成,则应确保它们在单独的线程中运行
例如,以下代码演示了一个点击侦听器从单独的线程下载图像并将其显示在 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();
}
可以看出它创建了一个新线程来处理网络操作,但是它违反了单线程模式的第二条规则:不要在 UI 线程之外访问 Android UI 工具包。在工作线程中修改了 ImageView, 这将使应用运行时出现错误
为解决此问题,Android 提供了几种途径来从其他线程访问 UI 线程:
- 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 线程中操纵 ImageView
此外,也可以使用AsyncTask来完成任务。AsyncTask 允许对用户界面执行异步操作。它会先阻塞工作线程中的操作,然后在 UI 线程中发布结果
要使用 AsyncTask ,必须创建 AsyncTask 的子类并实现 doInBackground() 回调方法,该方法将在后台线程池中运行。 要更新 UI,应该实现 onPostExecute() 方法以传递 doInBackground() 返回的结果并在 UI 线程中运行,以便安全地更新 UI
public void onClick(View v) {
new DownloadImageTask().execute(“http://example.com/image.png”);
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
protected Bitmap doInBackground(String… urls) {
return loadImageFromNetwork(urls[0]);
}
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
AsyncTask 工作方法如下所示:
-
使用泛型指定参数类型、进度值和任务最终值
-
doInBackground() 方法会在工作线程上自动执行
-
onPreExecute()、onPostExecute() 和 onProgressUpdate() 均在 UI 线程中调用
-
doInBackground() 返回的值将发送到 onPostExecute()
-
可以随时在 doInBackground() 中调用publishProgress()方法,以便在 UI 线程中执行 onProgressUpdate()
-
可以随时取消任何线程中的任务
这里提供本系列文章所有的 IPC 示例代码:IPCSamples
作者:叶志陈
链接:https://www.jianshu.com/p/5c94a6667877
更多系列教程GitHub白嫖入口:https://github.com/Timdk857/Android-Architecture-knowledge-2-
B站全套Android移动架构师进阶视频教程白嫖地址:https://space.bilibili.com/544650554
分享读者
作者2013年java转到Android开发,在小厂待过,也去过华为,OPPO等大厂待过,18年四月份进了阿里一直到现在。
被人面试过,也面试过很多人。深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长,而且极易碰到天花板技术停滞不前!
我们整理了一份阿里P7级别的Android架构师全套学习资料,特别适合有3-5年以上经验的小伙伴深入学习提升。
主要包括阿里,以及字节跳动,腾讯,华为,小米,等一线互联网公司主流架构技术。如果你有需要,尽管拿走好了。
35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
远的职业规划。35岁后的你只会比周围的人更值钱。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!