# å®åæ§è½ä¼å ## æ§è½ä¼åçå 大èè + Mobile Context + èµæºåé + å åï¼æ®éè¾å°ï¼512MBå¾å¸¸è§ï¼å¼åè çæºå¨ä¸è¬æ¯ç¨æ·çæºå¨é«ç«¯ + CPUï¼æ ¸å¿å°ï¼è¿ç®è½å没æå ¨å¼ + GPUï¼ä¸ä¼ 大ç纹çï¼textureï¼ï¼overdraw + å åå¼é大ï¼ä¼å¯¼è´ç³»ç»æ¢å ¥æ¢åºæ´é¢ç¹ï¼GCæ´é¢ç¹ï¼APP被killã被é坿´é¢ç¹ï¼ä¸ä» 伿¶èæ´å¤çµéï¼èä¸GC伿¶è大鿶é´ï¼ä½¿å¾åºç¨ç¨åºæ¸²æé度ä½äº60fpsï¼GCèæ¶dalvik 10-20msï¼ART 2-3msï¼ + å¤é¨åå¨ä¸ç½ç»ï¼ä¹æ¯åéçï¼éè¦èèèµæºç使ç¨ãç½ç»è¯·æ±çä¼å + The Rules: Memory + Avoid Allocations in Inner Loops + Avoid Allocations When Possible + Cached objects + Object poolsï¼æ³¨æçº¿ç¨å®å ¨é®é¢ + ArrayList v.s. æ°ç» + Android collections classesï¼HashMap v.s. ArrayMap/SimpleArrayMap + Methods with mutated objects + Avoid object types when primitive types will doï¼SparseIntArrayï¼SparseLongArray + Avoid arrays of objects + Avoid Iteratorsï¼æ¾å¼ä¸éå¼ï¼foreachè¯å¥ï¼ï¼ä¼å¯¼è´ä¸ä¸ªIteratorçåé ï¼å³ä¾¿æ¯ç©ºéåã + Avoid Enums + Avoid Frameworks and Libraries Not Written for Mobile Applications + Avoid Static Leaks + Avoid Finalizers + Avoid Excess Static Initialization + Trim caches on demand + Use isLowRamDeviceï¼ActivityManager.isLowRamDevice() + Avoid Requesting a Large Heap + Avoid Running Services Longer than Necessaryï¼BroadcastReceiverï¼IntentService + Optimize for Code Size + Use Proguard to strip out unused code + Carefully consider your library dependencies + Make sure to understand the cost of any code which is automatically generated + Prefer simple, direct solutions to problems rather than creating a lot of infrastructure and abstractions to solve those problems + The Rules: Performance + Avoid Expensive Operations During Animations and User Interaction å¨ç»çæ¯ä¸å¸§æ¸²æé½æ¯å¨UI线ç¨çï¼å¦ææå¨ç»çæ¶åè¿è¡èæ¶æä½ï¼å¾å¯è½å¯¼è´å¨ç»ä¸æµç ï¼èæ¶æä½å æ¬ï¼ + Layoutï¼å½å¨ç»æ£å¨ææ¾çæ¶åï¼è¦é¿å æ¹åViewï¼å»¶è¿æ¹åï¼ï¼åæ¶éæ©å¨ç»ä¹éè¦é¿å ä¼è§¦ålayoutçå¨ç»ï¼ä¾å¦translationXï¼translationYåªä¼å¯¼è´å»¶è¿çlayoutæä½ï¼èLayoutParams屿§ï¼åä¼å¯¼è´å³æ¶çlayoutã + Inflationï¼å¨ç»è¿ç¨ä¸é¿å inflateæ°çviewï¼æ¯å¦å¯å¨æ°çactivityï¼æè ListViewæ»å¨å°ä¸åtypeçåºåã + Launch Fast + Avoid this problem by launching as fast as possible + Also, avoid initialization code in your Application object + Avoid Complex View Hierarchies + One approach to avoiding complex nested hierarchies is to use custom views or custom layouts in some situations; it may be cheaper for a single view to draw several pieces of text and icons rather than have a series of nested ViewGroups to accomplish this. + ç»åçååå°±æ¯æ ¹æ®ä»ä»¬æ¯å¦éè¦åç¬åç¨æ·å®æäº¤äºï¼ååºç¹å»äºä»¶çï¼ + Avoid RelativeLayout Near the Top of the View Hierarchy RelativeLayoutéè¦ä¸¤æ¬¡measurement passesæè½ç¡®å®å¸å±æ£ç¡®ï¼åµå¥RelativeLayoutï¼æ¯å¹ä¹å ³ç³» + Avoid Expensive Operations on the UI Thread + Minimize Wakeups + Develop for the Low End + Measure Performance + The Rules: Networking + Donât Over-Syncï¼batch it up with other system requests with JobScheduler or GCM Network Manager. + Avoid Overloading the Server + Donât Make Assumptions about the Network + Develop for Low End Networks + Design Back-End APIs to Suit Client Usage Patternsï¼ç¸å ³æ°æ®ä¸ä¸ªè¯·æ±åå宿¯ï¼ä¸ç¸å ³çæ°æ®åæ¥å£ååï¼å®¢æ·ç«¯åºå¯¹è·åçæ°æ®å ·å¤è¶³å¤çä¿¡æ¯ï¼ + The Rules: Language and Libraries + Use Android-Appropriate Data Structures: ArrayMap, SparseArray + Serialization + Parcelableï¼å®åç³»ç»IPCæ ¼å¼ï¼æParcelåå°ç£çæ¯ä¸å®å ¨çï¼è§£å æ¹å¿ é¡»è½è®¿é®Parcelçç±»ï¼å¦åå°å¤±è´¥ï¼ç¹å®çç±»ï¼Bitmapï¼CursorWindowï¼å°è¢«åå°SharedPreferenceä¸ï¼èéè¿Parcelä¼ éçåªæ¯æä»¶çfdï¼å卿§è½ä¼åç空é´ï¼ä½æ¯ä¹è约äºå åï¼ + Persistable Bundlesï¼API 21å¼å ¥ï¼åºåå为XMLï¼æ¯æçç±»åæ¯Parcelå°ï¼ä½æ¯ä¸ºBundleåç±»ï¼æäºåºæ¯æ¹ä¾¿å¤çï¼ + Avoid Java Serializationï¼é¢å¤å¼éæ´å¤§ï¼æ§è½æ´å·® + XML and JSONï¼æçæ´ä½ï¼å¤ææ°æ®åºèèåè¿°é项 + Avoid JNI + éè¦èèå¤ç§å¤ç卿¶æï¼æéç¨longä¿å + java->jni, jni->javaè°ç¨å¼éé½å¾å¤§ï¼ä¸æ¬¡JNIè°ç¨åå°½å¯è½å¤çå·¥ä½ + å å管çï¼java对象管çjni对åºå¯¹è±¡ççå½å¨æ + é误å¤çï¼å¨è°ç¨JNIä¹åæ£æ¥åæ° + åæ°å¯¹è±¡å°½éâä¼ å¼âè°ç¨ï¼å³ï¼å±å¼åä¼ éï¼ä¸è¦å¨JNIéé¢ä½¿ç¨æéè®¿é®æåï¼é¿å JNIè¿ç¨ä¸å¯¹è±¡è¢«åæ¶ + Prefer Primitive Typesï¼å åãæ§è½ + The Rules: Storage + Avoid Hard-coded File Paths + Persist Relative Paths Only + Use Storage Cache for Temporary Files + Avoid SQLite for Simple Requirements + Avoid Using Too Many Databases + Let User Choose Content Storage Location + The Rules: Framework + Avoid Architecting Around Application Components + Services Should Be Bound or Started, Not Both + Prefer Broadcast over Service for Independent Eventsï¼Use broadcasts for delivering independent events; use services for processes with state and on-going lifecycle. + Avoid Passing Large Objects Through Binder + Isolate UI processes from Background Services + The Rules: User Interface + Avoid Overdraw + Avoid Null Window Backgrounds put the background drawable you want on the window itself with the windowBackground theme attribute and let those intervening containers keep their default transparent backgrounds. + Avoid Disabling the Starting Windowï¼windowDisablePreview/windowBackgroundï¼ + Allow Easy Exit from Immersive Mode + Set Correct Status/Navigation Bar Colors in Starting Window + Use the Appropriate Context + Avoid View-Related References in Asynchronous Callbacks + Design for RTL + Cache Data Locally + Cache User Input Locally + Separate Network and Disk Background Operations + Tools + Host Tools + Systrace + Alerts and the Frames, æç¤ºéå¸¸è¯¦å°½ï¼ææ¥æ§è½é®é¢å¾æ¹ä¾¿ + 使¯ä¸ç¥éæä¹å¼å¯ï¼monitorå¼å¯æ¥éï¼å½ä»¤è¡å¼å¯ä¹æ¥éï¼æ¯ææºç³»ç»çåå ï¼ + AllocationTracker + ASéæï¼ç¹å»æé®ï¼å¯¹APPè¿è¡æä½ï¼åç¹å»æé®ç»æï¼captureå°å¨AS䏿å¼ï¼æ¥çåªéåé äºå åï¼ææ¥å ååé æ§è½é®é¢å©å¨ + Traceview + æ ¹æ®Traceviewçç»æï¼æ¥çèæ¶æåé åçæ¹æ³ï¼åæåå ï¼æé«æ§è½ + Hierarchyviewer + æ¥çå½åview hierarchy䏿¯ä¸ªviewçç»å¶å®è·µï¼ç»å¶è¾æ ¢çè¯¥å·¥å ·ä¼ç»åºæç¤ºï¼ä¸åé¢è²ï¼ + MAT (Memory Analysis Tool) + å éè¿heap dumpæå å¿«ç §å¯¼åºï¼åéè¿MATè¿è¡åæï¼å®è·µï¼ï¼ + Memory Monitor + meminfo + On-device tools + StrictMode + Profile GPU rendering + Debug GPU overdraw + Animator duration scale + Screenrecord + Show hardware layer updates + [Speed up your app](https://speakerdeck.com/udinic/speed-up-your-app-droidcon-nyc-2015) + Rules + Always Measure + Use[Experience] Slow Device + Consider Trade-Offs + Memory tips + Bitmap's pixel format + Context Awareness + HashMap v.s. ArrayMap/Sparce*Array + LeakCanary + Alpha + TextView: setTextColor() instead of setAlpha() + ImageView: setImageAlpha() instead of setAlpha() + CustomView: handle alpha yourself by overriding onSetAlpha(), overriding hasOverlappingRendering() + Hardware Acceleration + view.setLayerType(View.LAYER_TYPE_HARDWARE, null) + view.animate()....withLayer().start() + 硬件å éé常éç¨äºå¨ç»ç渲æï¼ä½æ¯ä¹æéè¦æ³¨æçå°æ¹ï¼[ref](http://blog.danlew.net/2015/10/20/using-hardware-layers-to-improve-animation-performance/) + 硬件å éçåçæ¯GPU伿Viewç»å¶çç»æç¼åèµ·æ¥ï¼åç»çæ´æ°åªéè¦éæ°æ¸²æå³å¯ï¼çå»äºViewçç»å¶ï¼ä»¥åç»å¶æä»¤çä¼ è¾é¨åï¼ä½æ¯ç¡¬ä»¶å éä¸å¼å§çæ¶åæé¢å¤çåå§åå·¥ä½ï¼ç¼åï¼ + 妿Viewç¹å«ç®åï¼ä» ä» æ¯ä¸ä¸ªåé¢è²åºåï¼é£ç¡¬ä»¶å éçé¢å¤å¼éå¯è½å¾ä¸å¿å¤± + 妿Viewå¨å¨ç»è¿ç¨ä¸ä¸æinvalidateï¼æè å ¶å 容䏿ååï¼ç¡¬ä»¶å éçææå°å¤§æææ£ + 妿å¨ç»åçå¨ViewGroupä¸ï¼èå ¶åViewç¸å¯¹äºViewGroup乿¯å¨åçååæ¶ï¼å°±ä¸åºè¯¥æç¡¬ä»¶å é设置å¨ViewGroupä¸ï¼å 为å¨ç»è¿ç¨ä¸ViewGroupçå 容æ¯ä¸æååçï¼åViewä¹å¨ä¸æååï¼ï¼èæ¯åºè¯¥æå é设置å¨å个åViewä¸ + GPUåå¨ç©ºé´æéï¼ä» å½æå¿ è¦æ¶æä½¿ç¨ç¡¬ä»¶å é + profile GPU renderingåshow hardware layers updatesæ¯å¾å¥½çææè¯ä¼°å·¥å · ## è°·æå®åå¢éå¯¹äºæ§è½ä¼åç建议 + [Android performance patternsç³»åè§é¢](https://www.youtube.com/playlist?list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE)å·²ç»åºå°äºç¬¬ä¸å£ï¼å½å 乿å®åå¤§ç¥æ´çç¿»è¯ç[䏿æåç](http://hukai.me/android-performance-patterns/)ï¼ä½å°±åè¯»ä¹¦ä¸æ ·ï¼å¤§ç¥åäºå®æ´ç书ï¼ççæ¶åè¿æ¯è¦å个ç¬è®°çã以ä¸åªæ¯é对èªèº«æ åµçç¬è®°ï¼ä» ä¾åèã + S1E0: Render Performance + 60 fps, 16 msæ¯å¸§ + S1E1: Understanding Overdraw + å¼åè é项ï¼Show GPU Overdraw + é¿å 设置å¤éèæ¯ + S1E2: Understanding VSYNC + Refresh Rateï¼ä»£è¡¨äºå±å¹å¨ä¸ç§å å·æ°å±å¹ç次æ°ï¼è¿åå³äºç¡¬ä»¶çåºå®åæ°ï¼ä¾å¦60Hz + Frame Rateï¼ä»£è¡¨äºGPUå¨ä¸ç§å ç»å¶æä½ç帧æ°ï¼ä¾å¦30fpsï¼60fps + å½Refresh rateåFrame rateä¸ä¸è´æ¶ï¼å°ä¼åçtearingææï¼å±å¹çå 容被åæäºä¸ä¸ä¸¤é¨åï¼å嫿¥èªä¸¤å¸§çå 容 + åçç®è¿°ï¼è§é¢ï¼å¨ç»ï¼æ¯ç±éæå¸§å¿«éåæ¢è¾¾å°çææï¼ä¾å¦60 fpsï¼ï¼èæ¯å¸§æ¯ä¸ä¸ªå¾çï¼å ¶å 容就æ¯ä¸ä¸ªåç´ ç©éµï¼æ¾ç¤ºå±ç»å¶æ¯å¸§çæ¶åï¼æ¯éè¡ç»å¶è¯¥åç´ ç©éµçï¼çæ³æ åµä¸ï¼æ¾ç¤ºå±ç»å¶å®ä¸å¸§çåç´ ä¹åï¼å»è·åä¸ä¸å¸§çåç´ è¿è¡ç»å¶ï¼ä½å¦ææ¾ç¤ºå±ç»å¶ç¬¬ä¸å¸§çåç´ ç»å¶å°ä¸åï¼ä¿å帧åç´ ç©éµçbuffer被åå ¥äºç¬¬äºå¸§çåç´ ç©éµï¼èæ¾ç¤ºå±å¹¶ä¸ç¥éï¼ä»ä¼æ¥çä»ä¸ä¸è¡å¾ä¸ç»å¶ï¼å°±ä¼å¯¼è´ç»å¶åºæ¥çå¾åä¸é¨åå±äºä¸ä¸å¸§ï¼ä¸é¨åå±äºä¸ä¸å¸§ï¼å³tearingææã + VSyncï¼ç¨æ¥åæ¥GPUåå±å¹ç»å¶ï¼å¨GPUè½½å ¥æ°å¸§ä¹åï¼è¦çå¾ å±å¹ç»å¶å®æä¸ä¸å¸§çæ°æ® + è¿ææ´å¤å ³äºå¾å渲æçå 容ï¼ä¸éç¼å²çï¼éè¦æ©å±é 读 + 帧ç大äºå·æ°é¢çï¼60 fpsï¼æ¶ï¼æ¾ç¤ºå¾æµç ï¼å¸§çå°äº60 fpsæ¶ï¼ä¼æ¾ç¤ºéå¤å¸§ï¼å¸§ççªç¶ä»å¤§äº60 fpséå°ä½äº60 fpsæ¶ï¼ç¨æ·å°±ä¼æåå°å¡é¡¿çåçäºï¼ + S1E3: Tool: Profile GPU Rendering + å¼åè é项ï¼Profile GPU Rendering, On screen as bars + 两个åºåï¼èæé®ç设å¤ä¼æä¸ä¸ªåºåï¼ï¼ä»ä¸å°ä¸åå«è¡¨ç¤ºï¼ç¶ææ ç»å¶ã主çªå£ç»å¶ãèæé®çåºåç»å¶ + ä¸ç§é¢è² + èè²ï¼draw timeï¼åå»ºãæ´æ°display listææ¶èçæ¶é´ï¼onDraw彿°ä¸ä½¿ç¨Canvasè°ç¨çdraw*彿°çæ§è¡æ¶é´ï¼convert to GPU description, cache as display listï¼ + èè²è¿é«ï¼å¯è½å 为大éview被invalidateï¼éè¦éç»ï¼æè æ¯onDrawæ¹æ³çé»è¾è¿äºå¤æï¼æ§è¡æ¶é´é¿ + 红è²ï¼execute timeï¼Android 2D rendereræ§è¡display listææ¶èçæ¶é´ï¼éè¿Open GLæ¥å£ï¼ä½¿ç¨GPUç»å¶ï¼ï¼èªå®ä¹Viewè¶å¤æï¼GPU渲ææéæ¶é´è¶é¿ï¼ + 红è²è¿é«ï¼åå å¾å¯è½å°±æ¯Viewçææå¤ªå¤æï¼æé«çå³°å¼ï¼å¯è½æ¯å ä¸ºéæ°æäº¤äºè§å¾ç»å¶é æçï¼å¹¶éview被invalidateï¼èæ¯ç±»ä¼¼äºViewæè½¬è¿æ ·çååï¼éè¦å æ¸ ç©ºåæåºåï¼åéæ°ç»å¶ï¼ + æ©è²ï¼process timeï¼CPUéç¥GPU渲æç»ææ¶èçæ¶é´ï¼åæ¥è°ç¨ + æ©è²è¿é«ï¼å¯è½æ¯Viewå¤ªå¤æï¼æ¸²æéè¦å¤ªå¤æ¶é´ + S1E4: Why 60fps? 常è¯ï¼12 fpsè¿ä¹äºäººæå¿«é翻书ï¼24 fpsæ¯çµå½±ç常ç¨å¸§çï¼60 fpsç¨äºè¡¨ç°ç»ä¸½çå¨ç»ææ + S1E5: Android, UI and the GPU + Resterizationï¼æ æ ¼åï¼ï¼ç»å¶Buttonï¼Shapeï¼Pathï¼Textï¼Bitmapçç»ä»¶æåºç¡çæä½ï¼æ æ ¼åå°±æ¯å°è¿äºç»ä»¶çå 容æåå°ä¸åçåç´ ä¸è¿è¡æ¾ç¤ºï¼æ æ ¼åå¾èæ¶ï¼å¼å ¥GPUå°±æ¯ä¸ºäºå å¿«æ æ ¼åæä½ï¼ + CPUè´è´£æUIç»ä»¶è®¡ç®æPolygonsï¼Texture纹çï¼ç¶å交ç»GPUè¿è¡æ æ ¼åæ¸²æ + å æ¤éè¦å¨CPUåGPUä¹é´ä¼ éæ°æ®ï¼OpenGL ESå¯ä»¥æé£äºéè¦æ¸²æç纹çHoldå¨GPU Memoryéé¢ï¼å¨ä¸æ¬¡éè¦æ¸²æçæ¶åç´æ¥æä½ãå¦ææ´æ°äºGPUæholdä½ç纹çå 容ï¼ä¹åä¿åçç¶æå°±ä¸¢å¤±äºï¼å°å¯¼è´ç»å¶åæ ¢ã + å¨å®åç³»ç»ä¸ï¼ç±ä¸»é¢æä¾çèµæºï¼Bitmapsï¼Drawablesçï¼é½æ¯ä¸èµ·æå å°ç»ä¸çTexture纹çå½ä¸ï¼ç¶ååä¼ éå°GPUéé¢ï¼è¿æå³çæ¯æ¬¡ä½ éè¦ä½¿ç¨è¿äºèµæºçæ¶åï¼é½æ¯ç´æ¥ä»çº¹çéé¢è¿è¡è·å渲æçï¼é度å°ä¼æ´å¿«ã + 乿æ´å¤æçç»ä»¶ï¼ä¾å¦æ¾ç¤ºå¾ççæ¶åï¼éè¦å ç»è¿CPUç计ç®å è½½å°å åä¸ï¼ç¶åä¼ éç»GPUè¿è¡æ¸²æãæåçæ¾ç¤ºæ´å 夿ï¼éè¦å ç»è¿CPUæ¢ç®æçº¹çï¼ç¶åå交ç»GPUè¿è¡æ¸²æï¼åå°CPUç»å¶å个åç¬¦çæ¶åï¼åéæ°å¼ç¨ç»è¿GPU渲æçå 容ãå¨ç»åæ¯ä¸ä¸ªæ´å 夿çæä½æµç¨ã + S1E6: Invalidations, Layouts, and Performance + DisplayListï¼å å«éè¦GPUç»å¶å°å±å¹ä¸çæ°æ®ä¿¡æ¯ + å¨æä¸ªViewç¬¬ä¸æ¬¡è¢«æ¸²ææ¶ï¼ä¼å建DisplayListï¼å½è¿ä¸ªViewè¦æ¾ç¤ºå°å±å¹ä¸æ¶ï¼ä¼æ§è¡GPUçç»å¶æä»¤æ¥è¿è¡æ¸²æã妿åç»æç§»å¨è¿ä¸ªViewçä½ç½®çæä½èéè¦å次渲æè¿ä¸ªViewæ¶ï¼åªéè¦é¢å¤æä½ä¸æ¬¡æ¸²ææä»¤å³å¯ãå¦æä¿®æ¹äºViewä¸çæäºå¯è§ç»ä»¶ï¼å°éè¦è¿è¡å建DisplayListãæ§è¡æ¸²ææä»¤æ´ä¸ªè¿ç¨ã + ä¸è¿°æ¥éª¤å¯ç®å为ä¸å¾ï¼éè¦çæ¶é´åå³äºViewçå¤æåº¦ï¼Viewéç»å¼èµ·çView hierarchyçååçå¤æåº¦  + å¯ç¨å·¥å ·ï¼Profile GPU Renderingæ¥ç渲æçè¡¨ç°æ§è½ï¼Show GPU view updatesæ¥çè§å¾æ´æ°çæä½ï¼HierarchyVieweræ¥ççé¢å¸å±ç»æï¼ + ç®æ /è¦ç¹ï¼ä½¿å¸å±æå¹³åï¼ç§»é¤éå¿ è¦ç»ä»¶ï¼é¿å 使ç¨åµå¥layoutï¼å°¤å ¶æ¯æ ¹èç¹æ¹åçRelativeLayoutåæweightçLinearLayoutï¼ + S1E7: Overdraw, Cliprect, QuickReject + æ åç»ä»¶ï¼æå ¶ç»åï¼çOverdrawå¯ä»¥ä½¿ç¨å·¥å ·æ¥æ£æµãæ¶é¤ï¼åæ¶ç³»ç»ä¹ä¼é¿å ç»å¶å®å ¨ä¸å¯è§çç»ä»¶ï¼ + å®å ¨èªå®ä¹ç»ä»¶ï¼éåonDrawæ¹æ³ï¼ï¼ä¸è¿°æ¹æ¡å°æ æ³å®ç°ï¼å¯éè¿`canvas.clipRect()`æ¥å¸®å©ç³»ç»è¯å«å¯è§åºåï¼å®å ¨å¨ç©å½¢å¤é¢çå 容ï¼ç»ä»¶ï¼å°ä¸ä¼ç»å¶ã渲æï¼ä½æé¨åå¨ç©å½¢å çä»ä¼ç»å¶ã渲æï¼ + `canvas.quickreject()`彿°å¯ä»¥å¤ææ¯å¦åæä¸ªç©å½¢ç¸äº¤ï¼å¦æä¸ç¸äº¤ï¼åå¯ä»¥ç´æ¥è·³è¿ï¼ + æ§è½ä¼åæ»ååä¹ä¸ï¼å æµéææï¼åç°é®é¢åå¯»æ¾æ ¹æºï¼å°è¯æ¹è¿åè¦å次æµéææè¿è¡å¯¹æ¯ + S1E8: Memory Churn and performance + Androidçå å ååä»£åæ¶æ¨¡åå¦ä¸å¾ç¤º  + GCæ¶ä¼æåææå ¶ä»çº¿ç¨ï¼å¯¼è´GCé¢ç¹çå¯è½åå + Memory Churnï¼å åæå¨ï¼ï¼å¤§é对象被å建ï¼ç¶åç«å³è¢«éæ¯ï¼ä¾å¦å¨onDrawç彿°ä¸å建对象 + ç¬é´äº§ç大éç对象ä¼ä¸¥éå ç¨Young Generationçå ååºåï¼å½è¾¾å°éå¼ï¼å©ä½ç©ºé´ä¸å¤çæ¶åï¼ä¹ä¼è§¦åGCãåæ¶å¯è½è§¦åå ¶ä»åºåï¼ä»£ï¼çGC + 使ç¨Android studioçMemory Monitorï¼å¯ä»¥è§å¯æ¯å¦åå¨å åæå¨ï¼Memory monitoréæäºAllocation Trackerï¼ä½¿ç¨Allocation Trackerå¯ä»¥æ¥çæ¯ä¸ªçº¿ç¨çå ååé æ åµï¼å¯ä»¥å ·ä½å°æä¸ªå½æ°çæè¡ä»£ç + 平常éè¦æ³¨æçæ¯ï¼onDrawçè¿æ ·ä¼è¢«é«é¢çåå¤è°ç¨ç彿°ã循ç¯ä½å é¨çï¼é¿å å建æ°å¯¹è±¡ + S1E9: Garbage Collection in Android + å®åç³»ç»ä½¿ç¨çèææºæ¯ä¸ä»£æ¨¡åï¼Young, old, permanentï¼è¶å¾åæ¯ä»£GCæ¶é´è¶é¿ï¼ + åºè¯¥é¿å é¢ç¹GC + S1E10: Performance Cost of Memory Leaks + ä¸ä¸ªå ¸åçActivityæ³é²åºæ¯ï¼Activityç±»å é¨çééæHandleråç±»ï¼æå¿åç±»ï¼å®ä¾ + LeakCanaryå·¥å ·æ¯æ£æµå åæ³æ¼çå¥½å·¥å · + S1E11: Memory Performance + å·¥å ·éï¼**Memory Monitor**ï¼è§å¯æ¯å¦åå¨å åæå¨ï¼**Allocation Tracker**ï¼è¿½è¸ªå ååé æ åµï¼**Heap Tool**ï¼æ¥çå åå¿«ç §ï¼åæå¯è½æ³é²çå¯¹è±¡ï¼ + S1E12: Tool - Memory Monitorï¼æ çå¯è®° + S1E13: Battery Performance + å°½éåå°å¤éå±å¹ç次æ°ä¸æç»çæ¶é´ï¼ä½¿ç¨WakeLockæ¥å¤çå¤éçé®é¢ï¼è½å¤æ£ç¡®æ§è¡å¤éæä½å¹¶æ ¹æ®è®¾å®åæ¶å ³éæä½è¿å ¥ç¡ç ç¶æã + æäºéå¿ é¡»é©¬ä¸æ§è¡çæä½ï¼ä¾å¦ä¸ä¼ ææ²ï¼å¾çå¤ççï¼å¯ä»¥çå°è®¾å¤å¤äºå çµç¶ææè çµéå è¶³çæ¶åæè¿è¡ã + 触åç½ç»è¯·æ±çæä½ï¼æ¯æ¬¡é½ä¼ä¿ææ çº¿ä¿¡å·æç»ä¸æ®µæ¶é´ï¼æä»¬å¯ä»¥æé¶æ£çç½ç»è¯·æ±æå è¿è¡ä¸æ¬¡æä½ï¼é¿å è¿å¤çæ 线信å·å¼èµ·ççµéæ¶èã + Battery Historian Toolï¼æ¥çAPPçµéæ¶èæ åµ + JobScheduler APIï¼å¯¹ä»»å¡è¿è¡å®æ¶å¤çï¼ä¾å¦çå°ææºå¤äºå çµç¶æï¼æè¿æ¥å°WiFiæ¶å¤çä»»å¡ + JobSchedulerå¨API 21å¼å ¥ï¼Google play serviceæbackport: [GcmNetworkManager](https://developers.google.com/cloud-messaging/network-manager)ï¼ä¹æç¬¬ä¸æ¹[backport](https://github.com/evant/JobSchedulerCompat) + S1E14: Understanding Battery Drain on Android + 使ç¨WakeLockæè JobSchedulerå¤é设å¤å¤ç宿¶çä»»å¡ä¹åï¼ä¸å®è¦åæ¶è®©è®¾å¤åå°åå§ç¶æã + æ¯æ¬¡å¤éæ 线信å·è¿è¡æ°æ®ä¼ éï¼é½ä¼æ¶èå¾å¤çµéï¼å®æ¯WiFiçæä½æ´å çèçµ + S1E15: Battery Drain and WakeLocks + WakeLock使ç¨éç²¾å宿¶å¨ï¼å 许系ç»ä¸ºä¸ååºç¨çwake lock请æ±è¿è¡æå å¤çï¼è约çµéæ¶è + JobScheduler APIè¿è½åæ´å¤çäºæ ï¼ä¾å¦çå°å çµï¼æè è¿æ¥ä¸wifiæ¶å¤çä»»å¡ + S2E1: Battery Drain and Networking + æç»ç½ç»è¯·æ±ï¼ææ¹æ¬¡æ§è¡ï¼å¯é使¿æ´»ç½ç»ãçå¾ ä¼ç è¿ç¨çåæææ¬ï¼ä½¿ç¨JobSchedulerå¯ä»¥å®ç°æ´å¤çä¼åçç¥ï¼ + é¢åä¸å缩 + Android Studioä¸çNetworking Traffic Tool + adbå·¥å ·æ¥ççµéæ¶èï¼`adb shell dumpsys batterystats > xxx.txt`, `python historian.py xxx.txt > xxx.html` + å©ç¨`BatteryManager`å¨ä»£ç 䏿£æµæ¯å¦æ£å¨å çµï¼ä¹å¯ä½¿ç¨JobScheduleræ¥åï¼ + S2E2: Wear & Sensors + é¦å æä»¬éè¦å°½é使ç¨Android平尿ä¾çæ¢æè¿å¨æ°æ®ï¼è䏿¯èªå·±å»å®ç°çå¬ééæ°æ®ï¼å ä¸ºå¤§å¤æ°Android Watchèªèº«è®°å½Sensoræ°æ®çè¡ä¸ºæ¯æç»è¿åçµéä¼åçã + å ¶æ¬¡å¨Activityä¸éè¦ç嬿äºSensoræ°æ®çæ¶åéè¦å°½å¿«éæ¾ç嬿³¨åã + è¿ææä»¬éè¦å°½éæ§å¶æ´æ°çé¢çï¼ä» ä» å¨éè¦å·æ°æ¾ç¤ºæ°æ®çæ¶åæè§¦åè·åææ°æ°æ®çæä½ã + å¦å¤æä»¬å¯ä»¥é对Sensorçæ°æ®åæ¹éå¤çï¼å¾ æ°æ®ç´¯ç§¯ä¸å®æ¬¡æ°æè æä¸ªç¨åº¦çæ¶åææ´æ°å°UIä¸ã + æåå½Watchä¸Phoneè¿æ¥èµ·æ¥çæ¶åï¼å¯ä»¥ææäºå¤ææä½çäºæ 交ç»Phoneæ¥æ§è¡ï¼Watchåªéè¦çå¾ è¿åçç»æã + S2E3: Smooth Android Wear Animation + å¨ç»ä¼åä¾1ï¼å¨ä¸ä¸ªåå½¢çé表å¾ä¸ï¼æä»¬ææ¶éçæéæ åºæ¥å½ååç¬çå¾çè¿è¡æè½¬ä¼æ¯æè½¬ä¸å¼ 宿´çåå½¢å¾çæå½¢æç帧çè¦é«56% + å¨ç»ä¼åä¾2ï¼æèæ¯å¾çåç¬æåºæ¥è®¾ç½®ä¸ºä¸ä¸ªç¬ç«çViewï¼éè¿setLayerType()æ¹æ³ä½¿å¾è¿ä¸ªView强å¶ç¨Hardwareæ¥è¿è¡æ¸²æ + å¨ç»ä¼åä¾3ï¼ä½¿ç¨PropertyAnimationæè ViewAnimationæ¥æä½å®ç°ï¼Androidç³»ç»ä¼èªå¨å¯¹è¿äºAnimationåä¸å®çä¼åå¤ç + S2E4: Android Wear Data Batching + ä» ä» å¨çæ£éè¦å·æ°çé¢çæ¶åæååºè¯·æ± + å°½éæè®¡ç®å¤ææä½çä»»å¡äº¤ç»Phoneæ¥å¤ç + Phoneä» ä» å¨æ°æ®åçååçæ¶åæéç¥å°Wear + æé¶ç¢çæ°æ®è¯·æ±æç»ä¸èµ·åè¿è¡æä½ + S2E5: Object Pools + é¿å 对象çé¢ç¹å建ä¸éæ¯ï¼åå°å åæå¨ï¼é¿å éé级对象çå建ä¸éæ¯ï¼éä½å建å¼éï¼ + lazyåé v.s. é¢åé + æ ç¨ï¼éè¦æå¨éæ¾ï¼è°¨é²å åæ³æ¼ï¼ä¸ºäºç¡®ä¿ææç对象è½å¤æ£ç¡®è¢«éæ¾ï¼éè¦ä¿è¯å å ¥å¯¹è±¡æ± ç对象åå ¶ä»å¤é¨å¯¹è±¡æ²¡æäºç¸å¼ç¨çå ³ç³»ã + S2E6: To Index or Iterate? + for index ```java int size = list.size(); for (int i = 0; i < size; i++) { Object object = list.get(i); ... } ``` + Iterator ```java for (Iterator it = list.iterator(); it.hasNext(); ) { Object object = it.next(); ... } ``` + for simplified ```java for (Object object : list) { ... } ``` + æ§è½å¯¹æ¯ Fcn | Time taken(ms) --- | --- for index (ArrayList) | 2603 for index (Vector) | 4664 for simple (ArrayList) | 5133 Iterator (ArrayList) | 5142 for simple (Vector) | 11783 Iterator (Vector) | 11778 + S2E7: The Magic of LRU Cache + å®åç³»ç»æä¾äºLruCacheç±»ï¼å·²å®ç°LRUç®æ³ + æ ç¨ï¼æå¨éæ¾ç¼åç对象ï¼è°¨é²å åæ³æ¼ + S2E8: Using LINT for Performance Tipsï¼æ çå¯è®° + S2E9: Hidden Cost of Transparency + é常æ¥è¯´ï¼å¯¹äºä¸éæçViewï¼æ¾ç¤ºå®åªéè¦æ¸²æä¸æ¬¡å³å¯ï¼å¯æ¯å¦æè¿ä¸ªView设置äºalphaå¼ï¼ä¼è³å°éè¦æ¸²æä¸¤æ¬¡ + å¨æäºæ åµä¸ï¼ä¸ä¸ªå å«alphaçViewæå¯è½ä¼è§¦å该Viewå¨HierarchyViewä¸çç¶Viewé½è¢«é¢å¤éç»ä¸æ¬¡ + å¨å¨ç»å¼å§æ¶ï¼`setLayerType(View.LAYER_TYPE_HARDWARE, null)`ï¼å¨ç»ç»æåï¼`setLayerType(View.LAYER_TYPE_NONE, null)`ï¼å¨API >= 16æ¶ï¼å¯ä»¥åªè°ç¨`ViewPropertyAnimator.alpha(0.0f).withLayer()`æ¥å£å³å¯ï¼ + 使ç¨shadowæ¶ï¼éåViewç`hasOverlappingRendering()`æ¥å£ï¼è¿åfalseï¼ + åªæå½ç¡®å®ç¶é¢æ¯è¿é¨åviewçæ¸²ææ¶ï¼ææå¿ è¦è¿æ ·ä¼åï¼ + S2E10: Avoiding Allocations in onDraw()ï¼è®°ä½ï¼å®è·µå³å¯ + S2E11: Tool: Strict Mode + å¼åè é项Strict Modeï¼å¦æå卿½å¨ANR鿣ï¼ä¸»çº¿ç¨ç£çIOï¼ç½ç»è¯·æ±çï¼ï¼å±å¹ä¼éªç°çº¢è² + 乿代ç çAPIï¼`StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()...build());`å`StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()...build());`ï¼å¦ææéæ£ï¼å±å¹ä¼éªçï¼å¹¶ä¸ælogè¾åº + S2E12: Custom Views and Performanceï¼é¿å 以ä¸é®é¢ï¼ + Useless calls to onDraw()ï¼ä» å¨Viewå 容åçååæ¶æè°ç¨`View.invalidate()`ï¼å°½é使ç¨ClipRectçæ¹æ³æ¥æé«ç»å¶çæ§è½ï¼ + Useless pixelsï¼åå°ç»å¶æ¶ä¸å¿ è¦çå ç´ ï¼å¯¹äºé£äºä¸å¯è§çå ç´ ä¸è¦ç»å¶ï¼ + Wasted CPU cyclesï¼ä¸å¨å±å¹ä¸çå ç´ ï¼å¯ä»¥ä½¿ç¨Canvas.quickRejectæä»ä»¬ç»åé¤ï¼å¦å¤å°½é使ç¨GPUæ¥è¿è¡UIçæ¸²æï¼è¿æ ·è½å¤æå¤§çæé«ç¨åºçæ´ä½è¡¨ç°æ§è½ï¼ + S2E13: Batching Background Work Until Laterï¼ä¸æææ¶å + S2E14: Smaller Pixel Formats + dalvikèææºä¸ä¼èªå¨è¿è¡å åæ´ç + Android为å¾çæä¾äº4ç§è§£ç æ ¼å¼ï¼ARGB_8888, RGB_565, ARGB_4444, ALPHA_8ï¼ä½æ¯å®é æµè¯çæ¶åï¼å¦æå¾çä¸åï¼æ¾ç¤ºå¾ççViewåºåä¸åï¼ä¹ä¸éå¶BitmapåªæViewé£ä¹å¤§ï¼å纯设置`bitmapOption.inPreferredConfig`好忲¡ä»ä¹ç¨ + å¯ä»¥éè¿å°è§£ç çBitmap大å°è®¾ç½®ä¸ºView大å°ç两åï¼å使¯dpï¼ï¼å®æµå ååºæ¬å¯ä»¥éå°1/16ï¼å½ç¶åææ¯å¾çæ¯View大å¾å¤ï¼ï¼èä¸è§è§ææåºæ¬ä¸æ · + S2E15: Smaller PNG Filesï¼ä»¥ä¸å»ºè®®ç»å[微信å®åå¢éçå享](https://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=208008519&idx=1&sn=278b7793699a654b51588319b15b3013&scene=1&srcid=1007GhzCdgN0wjTjeQsPB4eD&key=2877d24f51fa5384290d7d8aa605c55ff1a8c3028340b6fbdb3d476a1fda87667eebd1129604641229b2cd82db1c6ee8&ascene=0&uin=MzMwMTQwNjU1&devicetype=iMac+MacBookPro11%2C2+OSX+OSX+10.11+build(15A284)&version=11020201&pass_ticket=q9AwYL2XRcpIhDNnzuhAhmTsVmpQnGy5XGihyNIkjYhsXqdSuOTUKGgil6IsiPyL) + 没æéæåº¦çæä»¶ï¼é½å¯ä»¥ç¨jpg + 对äºä½ç§¯ç¹å«å¤§(è¶ è¿50k)çå¾çèµæºå¯ä»¥èèææå缩ï¼jpgéç¨ä¼å¾å缩ï¼pngå°è¯éç¨pngquantå缩ï¼è¾åºè§è§å¤ææ¯å¦å¯è¡ï¼ + 对assetsä¸çå¾çèµæºä¹ä½¿ç¨aaptçcrunchåå¾çé¢å¤çï¼ + crunchæå¯è½ä¼ä½¿å¾çå大ï¼å¨è¿ç§æ åµï¼æä»¬å¯ä»¥æ¿æ¢æåå¾ãéè¦æ³¨æçæ¯å¯¹äº.9.pngï¼ç±äºcrunchè¿ç¨ä¸å»é¤äºé»è¾¹ï¼æä»¥ä¸è½æ¿æ¢ï¼ + å¯¹äºæ²¡æéæåºåçpngå¾çï¼å¯ä»¥è½¬æjpgæ ¼å¼ã + Webpï¼æ¢ä¿çpngæ ¼å¼çä¼ç¹ï¼åè½å¤åå°å¾çå¤§å° + S2E16: Pre-scaling Bitmaps + `bitmapOption.inSampleSize`屿§ï¼å¯çæ¯ä¾ç¼©æ¾å¾çï¼èä¸ä¸ä¼å è½½åå¾å°å å + inScaledï¼inDensityï¼inTargetDensityç屿§æ¥å¯¹è§£ç å¾çåå¤ç + inJustDecodeBoundsï¼åªä¼å 读åå¾ç尺寸ï¼ä¸ä¼å è½½å°å å + S2E17: Re-using Bitmaps + 设置äºin`bitmapOption.Bitmap`åï¼ç³»ç»ä¼å°è¯ä½¿ç¨å·²æçBitmapæ¥ä¿åæ°çå¾çï¼é¿å å åçåå¤å建ï¼ä½æ¯è¿ä¸æ¹æ³æäºä¸è¶³ï¼ + å¨SDK 11 -> 18ä¹é´ï¼éç¨çbitmap大å°å¿ é¡»æ¯ä¸è´ç + ä»SDK 19å¼å§ï¼æ°ç³è¯·çbitmap大å°å¿ é¡»å°äºæè çäºå·²ç»èµå¼è¿çbitmapå¤§å° + æ°ç³è¯·çbitmap䏿§çbitmapå¿ é¡»æç¸åçè§£ç æ ¼å¼ + å¯ä»¥ç»åå¯¹è±¡æ± ï¼ç»ä¸åè§£ç æ ¼å¼ï¼ä¸å大å°çå¾çåå¤ä¸åçBitmapå¹¶è¿è¡å¤ç¨ï¼ä¸è¿è¿æ ·åé¾åº¦è¾å¤§ + 弿ºå¾çå è½½åº[Glide](https://github.com/bumptech/glide)ï¼[Fresco](https://github.com/facebook/fresco) + S2E18: The Performance Lifecycle + Gatherï¼æµè¯æ¶éæ°æ® + Insightï¼åææ°æ® + Actionï¼è§£å³é®é¢ + 忬¡è¿è¡æµè¯ï¼éªè¯ææ + S2E19: Tools not Rulesï¼ä¸è¿°å»ºè®®éè¦çµæ´»åºç¨ + S2E20: Memory Profiling 101ï¼ä¸æå·²è¿° + S3E1: Fun with ArrayMaps; S3E2: Beware Autoboxing; S3E3: SparseArray Family Ties + Javaåç容å¨ç±»åªæ¯æå¯¹è±¡ï¼primitiveç±»åä¼èªå¨è£ ç®±/æç®±ï¼åå¨ä¸å®æ¶é´å¼éï¼è䏿²¡ææ¾å ¥KVæ¶ä¹ä¼åé å åï¼ç©ºé´å¼éä¼å¤§å¾å¤ + å®åç³»ç»æä¾äºåè½ç±»ä¼¼ç容å¨å®ç°ï¼ArrayMapï¼ç©ºé´å¼éæ´ä½ + 使ç¨ä¸¤ä¸ªæ°ç»å®ç°ï¼ä¸ä¸ªä¿åæå¥½åºçkeyçhashå¼ï¼å¦ä¸ä¸ªä¿åkey-value + æ¥æ¾æ¶å¯¹hashæ°ç»è¿è¡äºåæ¥æ¾ï¼æ¾å°å访é®key-valueæ°ç»ï¼å¦æå¯¹åºä½ç½®keyä¸åï¼åæ¯å 为æç¢°æï¼ååä¸åä¸ä¸¤è·¯æ¥æ¾ + æå ¥ãå 餿¶åå°æ°ç»å ç´ çæå ¥ä¸å é¤ï¼æçä½ä¸äº + æ°æ®éå¨1K个key-value对æ¶ï¼æ¶é´æ§è½å 乿 å·®å¼ï¼ä½æ¯ç©ºé´æ§è½æåå¾å¤ + ä»ä½¿ç¨å¯¹è±¡ä½ä¸ºKVï¼ä» ä» æ¯é¿å ä¸ç¨çå ååé + é¿å æ··ç¨åçç±»åä¸å¯¹åºboxç±»åï¼èªå¨è£ ç®±/æç®±ä¼æ¶åå°å¯¹è±¡çåå»ºï¼æ¶é´ã空é´åæä¸å®å¼é + SparseBooleanArray(int -> boolean), SparseIntArray(int -> int), SparseLongArray(int -> long), LongSparseArray(long -> Object), å以䏿¶å¯ä»¥èèä½¿ç¨ + S3E4: The price of ENUMs + enumä¼å ç¨æ´å¤çç£ç空é´ï¼ç¼è¯çclassæä»¶ï¼åè¿è¡æ¶å å + S3E5: Trimming and Sharing Memory + å¯ä»¥å¤ç`onLowMemory()`ï¼`onTrimMemory()` + onTrimMemory()çåè°å¯ä»¥åçå¨Applicationï¼Activityï¼Fragmentï¼Serviceï¼Content Providerã + ä»Android 4.4å¼å§ï¼ActivityManageræä¾äºisLowRamDevice()çAPIï¼é常æçæ¯Heap Sizeä½äº512Mæè å±å¹å¤§å°<=800*480ç设å¤ã + S3E6: DO NOT LEAK VIEWS + å½å±å¹åçæè½¬çæ¶åï¼activityå¾å®¹æåçæ³æ¼ + 弿¥åè°ä¹å¾å®¹æåçæ³æ¼ + å é¨ééæHandleråç±»å®ä¾ä¹å®¹æåçæ³æ¼ + é¿å 使ç¨Static对象 + é¿å æViewæ·»å å°æ²¡ææ¸ 餿ºå¶ç容å¨éé¢ + S3E7: Location & Battery Drain + é¢çè¶é«ï¼èçµè¶å¤§ + 精度è¶é«ï¼èçµè¶å¤§ + setFastestInterval()ï¼LocationRequest.setPriority() + S3E8: Double Layout Taxation + é¿å å¨é«å±çº§èç¹ä½¿ç¨ä¼ä¸¤æ¬¡layoutçLayoutï¼RelativeLayoutï¼ä½¿ç¨weightçLinearLayout/GridLayout + æå¹³åview hierarchyï¼åå°å±çº§ + ListView/RecyclerViewè¿æ ·çitem viewéé¢ä¹è¦å°¤å ¶æ³¨ææ¸²ææ§è½ + å¨ä»»ä½æ¶åé½è¯·é¿å è°ç¨requestLayout()çæ¹æ³ï¼å ä¸ºä¸æ¦è°ç¨äºrequestLayoutï¼ä¼å¯¼è´è¯¥layoutçææç¶èç¹é½åçéæ°layoutçæä½ + å¯ä»¥ä½¿ç¨Systraceæ¥è·è¸ªç¹å®çææ®µæä½ + S3E9: Network Performance 101 + æå æ¹éåéè¯·æ± + éå½é¢å + éå½å缩 + S3E10: Effective Network Batching + S3E11: Optimizing Network Request Frequencies + S3E12: Effective Prefetching ## Squareå¢éç建议 + [Eliminating Code Overhead by Jake Wharton](https://www.youtube.com/watch?v=b6zKBZcg5fk&feature=youtu.be) + CPU + Do not nest multi-pass layouts: RelativeLayout, LinearLayout with layout_weight... + Lazily compute complex data when needed + Cache heavy computational results for re-use + Consider RenderScript for performance + Keep work off main thread + Memory + Use object pools and caches to reduce churn (judiciously) + Be mindful of the overhead of enums + Do not allocate inside the draw path + Use specialized collections instead of JDK collections when appropriate (SparceArray...) + I/O + Batch operations with reasonable back-off policies + Use gzip or binary serialization format + Cache data offline with TTLs for reloading + Use JobScheduler API to batch across OS + Spectrum of optimizations, not binary + Do not blindly apply to everything, only appropriate + Multiple micro-optimizations can improve like macro + ArrayListåé ï¼ä¼æä¸ä¸ªé»è®¤åå§å¼ï¼ä»¥å空é´ä¸å¤æ¶æåå¢çç¥è¿è¡æ©å± + 妿å建æ¶å°±ç¥éå ¶å¤§å°ï¼åå¯ä»¥newä¸ä¸ªå·²ç¥å®¹éçArrayListï¼é¿å å颿©å®¹ãæ°æ®å¤å¶çææ¬ + + StringBuilderï¼åæ ·çï¼ä¹å¯ä»¥å ç»ä¸ä¸ªé¢ä¼°ç大å°ï¼ç¶åç´æ¥åå§å该大å°çStringBuilderï¼å®åå¼åbuildæ¶ä¼èªå¨æStringçæ¼æ¥æä½è½¬å为StringBuilderå®ç°ï¼ç¶èè¿ç§èªå¨çè½¬æ¢æªå¿ é«æï¼ + ä¾å ```java for (int x = 0; x < valueCount; x++) { cleanFiles[x] = new File(directory, key + "." + x); dirtyFiles[x] = new File(directory, key + "." + x + ".tmp"); } ``` ===>>> ```java StringBuilder b = new StringBuilder(key).append("."); int truncateTo = b.length(); for (int x = 0; x < valueCount; x++) { b.append(x); cleanFiles[x] = new File(directory, b.toString()); b.append(".tmp"); dirtyFiles[x] = new File(directory, b.toString()); b.setLength(truncateTo); } ``` + å ¶ä» + 坹彿°çè°ç¨ï¼å°¤å ¶æ¯è彿°ãæ¥å£å½æ°ï¼ç»æï¼å¦æåä¸ä¸ªä½ç¨å䏿夿¬¡è°ç¨ï¼ä¸ç»æç¡®å®ä¸åï¼åºè¯¥å°ä»ä»¬è½¬åä¸ºä¸æ¬¡è°ç¨ï¼`for (int i = 0, size = list.size(); i < size; i++)` + 对éåçéåï¼ä¸è¦ä½¿ç¨è¯æ³ç³ï¼ä¼æé¢å¤å¼éï¼Iteratorå建ãè彿°è°ç¨çï¼ ## [NimbleDroidç建议](http://blog.nimbledroid.com/2015/09/17/how-to-make-your-application-fluid.html) + æ§è½ä¼åçæµç¨  + Recommendation 1: limit app startup to 2 seconds + Recommendation 2: eliminate hung methods + Recommendation 3: measure as often as you canï¼æä¹ãä»ä¹ç²åº¦çprofilingå¢ï¼ + Recommendation 4: know a set of common issues + ClassLoader.getResourceAsStream() + Recommendation 5: avoid surprises in 3rd-party SDKs