接下来呢我会把视频中的英文字幕逐句抄写下来,然后以英文句号分段,中间会穿插着相应的翻译,可能翻译的不准确,毕竟我英文水平也确实不是很好,但英文重要,所以我才通过学习 Android 的同时提升英文阅读水平,所以我尽量不翻译错,如果有错误,请留言指出。
本期视频地址: https://www.youtube.com/watch?v=qk5F6Bxqhr4&t=27s
(3分钟出头的视频老外竟然说了这么多...心好痛)
Ah, threading.
喔,线程。
So powerful that you can fold genomes with it, but so difficult that it can drive the average programmer insane.
fold genomes 折叠基因组是啥意思...我觉得这句大概是就是说线程它确实非常强大,但也并不是那么容易被驾驭的,所以它逼疯了很多程序员(估计是他有很多使用技巧,大家并不知道)。
My name is Cole McCandless, and as far as Android developer is concerned, threading is one of the most important and confusing things that you can deal with, which means if you want to write the fastest app possible, you've gotta take a minute and understand the subtle art that is multithreaded programming.
我叫 Cole McCandless,对于 Android 开发者而言,线程是你将会碰到的最重要和复杂的东西,这意味着如果你想要写出更快的 App,那么你需要花费一些时间去学习多线程编程的微妙的艺术。
Remeber that in the vast world of Android functions there's a whole boatload of operations that only execute on the main thread——system events, input events, application callback services, and even alarms.
请记住在 Android 这个庞大的世界体系中有一些操作只能在主线程去执行他们包括——系统事件,输入事件,应用回调服务以及 Alarm。
And for the most part, any code that you write executes inside one of these operations, which means it also runs on the main thread.
而大多数情况下,你编写的代码都会在上面那些操作中去执行,这就意味着你写的代码也是将运行在主线程的。
Now, if you recall, work that executes on the main thread gets there after being pulled from the front of a work queue, so blocks of work are done in order, and the next blocks of work isn't processed until the current one is completed, whice means if there is a large chunk of work between an input event and its callback, then the user will have to wait longer than expected to see results.
这句话有点难翻译,我认为大概意思是说,如果你还记得,代码是在主线程被执行的,并且有它自己的执行顺序,在它被拉到工作队列的前面,你需要等到它前面的执行完了才能执行下一个任务,这意味着,如果输入事件和它的回调之间有很大的一块代码要执行,那用户将会在超出预期的时间后看到结果。这段主要是说如果把事情都放在主线程去处理会影响事件和回调的处理时间,从而影响用户对 App 的体验,因为他们其实认为我不必等待就可以看到我想要的结果,这才是用户想要的。
And don't forget that the main thread is also where most of the screen rendering occurs.
并且不要忘记主线程也发生大部分屏幕渲染的地方。
While an animation or screen update is occurring, the system will try to draw the screen every 16 milliseconds or so to achieve smooth 60 frames per second.
当动画和界面更新发生的时候,系统将会尝试每 16 ms 绘制屏幕以达到每秒平滑的 60 帧。这里说到了系统会在每 16 ms 去重新绘制屏幕,而如果需要绘制过于复杂的界面就可能会导致卡顿,因为它上去并不平滑,这时候就需要我们去手动优化了。
The problem is that this is happening while the thread is also responding to app input events.
问题是主线程除了绘制界面还需要响应 App 的输入事件。
So if your app is in the middle of an animation and some random work packet takes longer than expected, you miss your chance to render that next frame within the 16 millisecond window, and that frame will be delayed.
大概意思是说如果你的 App 在你刷新界面期间你的代码很多要去执行的,那么你可能错过 16 ms 渲染下一帧的机会,它会被延迟到下一次被执行。这也就是为什么会有界面刷新看上去卡顿的原因,因为本来应该这一次被绘制的帧被延迟到了下一次。
This is what we call a dropped frame, and when this happens, users start to notice.
这被称之为掉帧,而用户可以察觉到的它的发生。明显的界面显示不流畅,是被称之为差的用户体验的。
The direct solution here is to move anything that might upset the 16 millisecond window over somewhere else, like to a different thread.
直接的解决方案是移动任何可能导致错过 16 ms 内绘制的代码,比如把可能长时间执行的代码放入到其他线程中去。
This way it won't be contesting with the UI thread for work to be done, and won't be interrupting the drawing of the screen, which is the whole point threading on Android in a nutshell.
这样(说的是上一句可以另起一个线程)它就不必和UI线程去竞争,不会打断屏幕绘制,which is the whole point threading on Android in a nutshell.这句话好难翻译...毕竟主线程是非常重要的。
So the question at hand, what's the best way to offiload this work, and how do you choose what types of work to offload?
所以手头的问题是什么是最好的处理方式并且如何选择。
Thankfully, the Android framework and provided a handful of classes to help make this a bit easier for you.
感谢的是 Android 提供了一些有帮助的类使得解决问题变得简单。
For example, the AsyncTask class is ideal for helping you get work on and off the UI thread the right way.
例如 AsyncTask 类是一个理想的可以帮我们正确使用 UI 线程的方法,因为它内部封装了线程池,你只需告诉他你需要在后台做什么,需要返回什么数据,它会自己帮我们处理好这些,耗时的操作被放到了后台线程而返回结果可以在主线程被拿到,但感觉生活中很少会有人用到它。
HandlerThreads are great when you need a dedicated thread for callbacks to land on.
当我们需要一个专用的线程来回调时,HandlerThreads 是很不错的选择。因为对我们来说如果我们在主线程去使用Handler时,主线程自带了一个 Looper,而在其他线程使用Handler时却需要注意自己手动创建一个 Looper,HandlerThread 是 Android 已经帮我们封装好的线程,它已经为我们提供好了一个 Looper,不需要我们手动去调用 Looper.prepare() 和 Looper.loop()。
ThreadPools work best when you break you work up into really small packets, and then toss them to a bunch of threads, and IntentServices are really ideal for background tasks, or when you need to get intent work off the UI thread.
线程池是当我们有很多需要太后处理的任务时不错的选择,因为它自己会我们管理线程,包括线程的创建、销毁和复用等等,IntentServices 是一个很不错的后台服务,服务本身是 Android 四大组件之一,自定义的服务我们需要自己去管理它的生命周期,IntentServices 它会在执行完我们指定任务后调用 stopSelf 去结束自己,它的源码很短所以建议大家去看看,它是通过 HandlerThread 把 onHandleIntent 的任务指定在后台线程去做,在 onStart 时通过 Handler 去通知后台线程执行 onHandleIntent 和 stopSelf,从而自己管理了自己。
And like everything else, there is not a silver bullet here, but knowing which primitive is best for what situation can save you a lot of headaches.
这句话大概意思是说和其他的一样,这里并没有最合适的方法,你需要根据自己的需求判断哪个更适合自己当前使用。
But note that having all those fancy helper classes doesn't hide the big problem, memory.
但请注意拥有这些方便操作类并不会隐藏一个很大问题,内存。
See threading and memory have never really played well, and on the Android platform it's no different.
大概意思是我们看得出线程和内存并没有相处的很好,在 Android 平它是也没有什么不同。
For example, if you declare one of those fancy threading primitives inside
of an activity, it now contains an implicit reference to the outer activity, which can cause a memory leak if the activity is destroyed, but the threaded work is still alive.
例如,我们在 Activity 中声明了一个线程,而这个线程包含了外部Activity的一个隐式的引用,如果 Activity 被销毁但线程还活着那么它可能会导致内存的泄露。
Or, what happens when the user rotates the device, destroying an activity that spawned a bunch of threaded work?
大概意思是,当用户旋转屏幕时会发什么什么?会销毁 Activity,而这个 Activity 上面还有这个大量的工作线程(这个我真的没有注意过)。
I mean, chances are that those work packets would have references back to various UI objects that don't really exist anymore.
我的意思是,它们还会引用着那些已经不存在的UI对象。所以弱引用是的不错的选择,如果引用还在就继续使用,如果引用已经被回收就不能继续使用了,当然使用什么引用还是需要根据自己的需求。
And the truth is that the Android platform is flooded with threads.
事实上Android平台上充斥着大量线程。
If you need a reminder of that grab a Systrance capture and check out all the cool stuff that's going on underneath the hood that you never really knew about.
这句话啥意思坑爹呢。。。大概是说利用 Systrance 可以捕捉和检查一些问题。
See, at the end of the day threading is critical to ensure high performance of your Android app, but there's lots of other problems that you have to worry about that as well, which is why you should check out the rest of Android Performance Pantterns videos.
线程对于确保 Android App 的高性能确实至关重要,但也有很多其他的问题需要我们去关心,这也是为什么我们应该看完其他 Android Performance Pantterns 视频的原因(哈哈哈实力推荐自己的视频666666)。
And also, don't forget to jion our Google+ community so that you can ask questions when you run into problem.
别忘了加入他们Google+中的交流,让你遇到问题他们会给出解答。大概是这里https://plus.google.com/u/0/collection/Yztxb
So keep calm, profile your code, and always remember, perf matters.
保持冷静,配置你的代码(?是这么翻译么)。
这是我翻译的第一篇,英语水平还不够好,不过也正是因为不够好才要去做这个,所以你也看到了我在翻译的过程中会加入一些自己的理解,希望对你有帮助。如有翻译不正确的地方请留言。