Android Development Interview: Android Knowledge Answers

Table of contents

Android

four major components

AMS

Activity

Service

BroadcastReceiver

ContentProvider

Fragment

Handler: Mechanism for inter-thread communication

Hander message distribution mechanism

HandlerThread

IdleHandler

View

Window

View drawing

Custom View

View event distribution mechanism

RecyclerView

WebView

animation

Bitmap

Binder

Serialization

What are the IPC communications

What is Binder

Binder principle

Intent size limit

AIDLCommunication

performance optimization

ANR

memory optimization

start optimization

Layout optimization (drawing optimization)

Caton optimization (frame rate optimization)

Network Optimization

CPU optimization

security optimization

system start

System startup process

SystemServer、ServiceManager、SystemServiceManager关系

Why not leave it to SystemServer to incubate the application process, but design a Zygote

Why does Zygote's IPC communication mechanism use socket instead of binder?

App start, package, install

Application launch process

Apk Composition

Apk packaging process

Similarities and differences between assets and res/raw

Apk Signing Process

Apk installation process


Android

four major components

AMS

  1. What is AMS: a. ActivityManagerService is mainly responsible for the startup, switching, scheduling of the four major components in the system and the management and scheduling of application processes. Its responsibilities are similar to the process management and scheduling modules in the operating system; b. In the system startup process Among them, AMS will be initialized when the SystemServer process is started; c. To open a new App, AMS is required to notify the zygote process, and all Activity life cycles are controlled by AMS
  2. ActivityThread and ApplicationThread: ActivityThread (Android main thread, after creating a new process, the main function of ActivityThread is loaded, and then executes a loop cycle to make the current thread enter the message loop), ApplicationThread (is the internal class of ActivityThread, is a Binder object .Here it is the server side of the IApplicationThread object waiting for the client side request, and then the Handler distribution processing, the largest client is AMS)
  3. Instrumentation: a. The interactive work between AMS and ActivityThread, such as the creation and suspension of Activity, is actually performed by Instrumentation; b. Each Activity holds a reference to an Instrumentation object, and there is only one Instrumentation in the entire process; c. mInstrumentation is initialized in the ActivityThread::handleBindApplication function; d. mInstrumentation.execStartActivity() is called inside the Activity.startActivity method, which is called to AMS, and then AMS informs the Zygote process to fork the child process through socket communication
  4. How AMS communicates with the zygote process: When the application starts, the Launcher process requests AMS, AMS sends a request to create an application process, and the Zygote process accepts the request and forks the application process. Specific communication process: a. The client process initiates a request; b. Call the Process.start() method to create a new process; c. Internally call ZygoteProcess.start and then call ZygoteState.connect(), ZygoteState is the internal class of ZygoteProcess; d. Zygote server After receiving the parameters, call ZygoteConnection.processOneCommand() to process the parameters, and fork the process; e, finally find the main() method of the ActivityThread class through findStaticMain() and execute it, and the child process starts
  5. Task stack: ActivityRecord (a, is the smallest unit of Activity management, corresponding to a user interface; b, is the representative of the application layer Activity component in AMS, each Activity started in the application has an ActivityRecord instance in AMS To correspond to it, this ActivityRecord is created with the start of the Activity, terminated and destroyed), TaskRecord (task stack, each TaskRecord may have one or more ActivityRecords, and the ActivityRecord on the top of the stack represents the currently visible interface), ActivityStack ( It is used to manage TaskRecord in the system, and maintains an ArrayList internally), ActivityStackSupervisor (manages multiple ActivityStacks, but currently there is only one ActivityStack that gets the focus (Focused), AMS uses it to manage Activities and is as unique as AMS) , ProcessRecord (records all ActivityRecords belonging to a process, ActivityRecords running in different TaskRecords may belong to the same ProcessRecord)
  6. AMS principle: Get this proxy object ActivityManagerProxy through ActivityManagerNative.getDefault in ActivityManager.getRunningServices. ActivityManager (interacts with all running Acitivity in the system, manages and maintains Activity-related information, holds ActivityManagerPorxy, and only needs to operate this proxy object to operate its business method AMS), ActivityManagerNative (is an abstract class, inherits Binder and Binder implements the IBinder interface and implements the IActivityManager interface. What really works is its subclass AMS), ActivityManagerProxy (the internal proxy class of ActivityManagerNative, which also implements the IActivityManager interface)

Activity

  1. Life cycle: 7 life cycles in general + life cycle in special cases. a. ActivityA jumps to ActivityB (A:onPause-B:onCreate onStart onResume-A:onStop); b. ActivityB presses the return key (B:onPause-A:onRestart onStart onResume-B:onStop onDestory); c. When ActivityB's When the launchMode is singleInstance, singleTask and the corresponding ActivityB has a reusable instance (A:onPause-B:onNewIntent onRestart onStart onResume-A:onStop (if A is removed from the stack, there is another A:onDestory)) d, when ActivityB When the launchMode is singleTop and ActivityB is already at the top of the stack (some special cases such as clicking on the notification bar and connecting points), only page B itself has life cycle changes (B:onPause onNewIntent onResume)
  2. onSaveInstanceState and onRestoreInstanceState call timing: a, call in pairs when switching between horizontal and vertical screens (onPause-onSaveInstanceState-onStop-onDestroy-onCreate-onStart-onRestoreInstanceState-onResume, Note: If you configure this property: androidconfigChanges="orientation|screenSize" will not be changed again Calling the life cycle of the Activity will only call the onConfigurationChanged method); b. It is recycled in the background and calls onRestoreInstanceState when the most recent program is opened; c. Menu key, Home key, power key, opening another Activity, etc. will call onSaveInstanceState, back key onSaveInstanceState will not be called
  3. Start mode: 4. Reduce waste of resources. SingleTop (Activity is at the top of the stack -> onNewIntent; non-stack -> create a new Activity; applied to -> notification page, login page, time-consuming operation return page), SingleTask (Activity already exists in the attribution stack -> all on the Activity Activity pops out of the stack and calls onNewIntent; applied to -> main interface), SingleIntance (only one such instance exists in the entire system. Different applications open this activity and share the same activity. Create a new stack, and then create the Activity instance And push it into the new stack, only this one Activity instance will exist in the new stack; apply to -> call interface)
  4. Start mode: display start (Intent construction, setComponent(componentName) method, setClass/setClassName method), implicit start (implicit Intent is to set action, data, category in the AndroidManifest file, let the system filter out the appropriate Activity)
  5. IntentFilter matching rules: action (if there is an IntentFilter rule, at least one action must be specified, and one of them must be specified when starting implicitly), category (if there is a rule, it can be specified or not), data (if there is a (Uri+MiniType) rule, then must be specified, full match is required)
  6. scheme: a. Usage scenario (APP jumps to another APP specified page according to the URL, can jump to the original page of the app through the h5 page, and the server can customize the jump to the app page); b. Protocol format (scheme://host: 8080/path?query, protocol name://address domain: path port number/specified page path? pass parameters, such as: local://agg:8080/test?testId=1935); c, use ( ); d, call(startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("local://agg:8080/test?testId=1935"))))
  7. Startup process (process): cross-process startup (a, the current process requests AMS: the current process uses Binder IPC to initiate a startActivity request to the system_server process (AMS); b, AMS sends a request to create an application process: after the system_server process receives the request, it sends a request to zygote The process sends a request to create a process; c, the Zygote process accepts the request and forks the application process, that is, the App process; d, the App process sends an attachApplication request to the AMS through the Binder, and the AMS binds the ApplicationThread; e, AMS sends a start Activity request: the system_server process is in After receiving the request, after a series of preparatory work, send the scheduleLaunchActivity request to the App process through the binder IPC; The main thread (ActivityThread) sends a LAUNCH_ACTIVITY message; after receiving the Message, the main thread creates the target Activity through the launch mechanism, and calls back methods such as Activity.onCreate, onResume, etc. After the UI rendering is completed, you can see the main interface of the App), start in the process (a. The current process requests AMS; b. AMS sends a request to start the Activity: after the system_server process receives the request, it parses the Activity information, processes the startup parameters, and sends a scheduleLaunchActivity request to the current process... (similar to cross-process startup, mainly without The part that creates a new process))
  8. Activity task stack: FLAG_ACTIVITY_NEW_TASK (specify "singleTask" startup mode for Activity, its effect is the same as specifying in XML android:launchMode="singleTask"), FLAG_ACTIVITY_SINGLE_TOP (specify "singleTop" startup mode for Activity, its effect is the same as specified in XML The same as android:launchMode="singleTop"), FLAG_ACTIVITY_CLEAR_TOP (Activity with this flag, when it starts, the Activity above it in the same task stack will be popped. This flag is generally used together with the singleTask startup mode In this case, if the activated Activity instance exists, the system will call its onNewIntent), FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS (will not appear in the history Activity list), taskAffinity (use the package name to specify the task stack)
  9. Activity freeze reasons: frequent GC (memory leaks, loading large data, large pictures), UI drawing (UI thread time-consuming operations, over-drawing)

Service

  1. The difference between startService and bindService: the life cycle callbacks are different (3 and 4). startService (onCreate() -> onStartCommand() -> onDestroy() If the service is already started, multiple executions of startService will not repeatedly execute onCreate(), but will call onStartCommand() and onStart()), bindService (onCreate( ) -> onBind() -> onUnbind()-> onDestroy() If the service is already enabled, the onCreate and onBind methods will not be called multiple times when bindService is executed multiple times)
  2. Startup process: It is consistent with the Activity startup process, just replace the Activity part with Service
  3. bindService process: a. Activity calls bindService, and notifies AMS to start Service through Binder; b. AMS creates ServiceRecord, and uses ApplicationThreadProxy callback to notify APP to create and start Service; c. After AMS starts Service, let Service return a Binder object Give it to yourself so as to pass it to the Client; d. AMS passes the Binder object obtained from the Service to the Activity through onServiceConnected; e. In the onServiceConnected callback, use the asInterface function of the Stub to convert the Binder into a proxy Proxy to complete the conversion of the business proxy. Then you can use Proxy to communicate
  4. The difference between the system service and the service started by bindService: a. Startup method: system service (itself implements the Binder interface, generally when the system starts, it is created by the SystemServer process and registered in the ServiceManager as a Binder entity, managed by the ServiceManager, located in the SystemServer In the process, such as: AMS, WMS, PMS), ordinary services (usually through the startService of the Activity or the startService of other contexts to call the services started by AMS, the Service component here is just a package, mainly the Binder service entity class inside, the same as the Activity Management is similar); b. Service registration and management: system services (usually registered through ServiceManager’s addService, these services generally need to have specific permissions to register with ServiceManager), common services (registered to AMS, AMS management service method is the same as ServiceManager is different, it adopts the management model of Activity); c, service request usage method: system service (get the service handle through ServiceManager's getService, this process is actually to query the registration system service in ServiceManager), ordinary service (go to AMS To find the corresponding Service component, the handle of the Binder inside the Service will eventually be passed to the Client)
  5. Service and Activity communicate with each other: Activity can communicate with Service through Binder object (a. Add an internal class that inherits Binder to Service, and add corresponding logical methods; b. Rewrite the onBind method of Service in Service, and return the internal class just defined Class instance; c. Bind service in Activity, rewrite ServiceConnection, the IBinder returned by onServiceConnected is the binder in Service, so you can directly call the corresponding logic method of Service in Activity), or communicate with Service through broadcast or EventBus; Service can communicate with Activity through broadcast and EventBus
  6. IntentService: a. By default, a worker thread HandlerThread is enabled to process all startup requests one by one, and the service will be automatically stopped after all tasks are executed; b. Application scenario: background download task, silent upload; c. Implementation mechanism: 1. Create a service called ServiceHandler Internal Handler; 2. Bind the internal Handler to the child thread corresponding to HandlerThread; 3. HandlerThread starts the thread to create its own looper; 4. Insert tasks into the work queue in turn through onStartCommand() and send them to onHandleIntent() Process one by one
  7. onStartCommand return value: START_NOT_STICKY (If the system terminates the service after onStartCommand() returns, the system will not rebuild the service unless there is a pending Intent to deliver. This is the safest option to avoid when it is not necessary, and the application can When all outstanding jobs are easily restarted, run the service), START_STICKY (if the system terminates the service after onStartCommand() returns, the service will be rebuilt and onStartCommand() will be called, but the last Intent will not be re-delivered. Instead, unless there is a pending Intents to start services (in this case, these Intents are delivered), otherwise the system calls onStartCommand() with a null Intent. This is suitable for media players (or similar services that do not execute commands, but run indefinitely and wait for jobs )), START_REDELIVER_INTENT (if the system terminates the service after onStartCommand() returns, it will rebuild the service and call onStartCommand() with the last Intent passed to the service, which is suitable for actively executing jobs that should be resumed immediately (such as downloading files) service )
  8. Mix bindService and startService: a, first startService, then bindService: onCreate() -> onStartCommand() -> onBind(); b, first bindService, then startService: onCreate() -> onBind() -> onStartCommand(); c. Only call stopService: the OnDestroy() method of Service will not be executed immediately, and OnDestroy will be executed when the Activity exits; d. Only call unbindService: only the onUnbind method will be executed, and onDestory will not be executed. If you want to completely exit the Service, you need Call unbindService() and stopService

Reference: Service_Swuagg's blog of the four major components of Android-CSDN blog

BroadcastReceiver

  1. Broadcast classification: ordinary global broadcast (can be processed in parallel, a way for communication between applications, between applications and systems, and within applications, using the binder method to achieve cross-process communication), system broadcast (only when registering broadcast receivers Just define related actions, no need to manually send broadcasts (network changes, lock screen, flight mode)), orderly broadcasts (sorted by Priority attribute values ​​from large to small, those with the same Priority attribute, dynamic registration broadcast priority), application Local broadcast (LocalBroadcast, more secure and efficient, used in the application and can only be registered dynamically, based on observer mode and Handler to implement the message bus model), sticky broadcast (StickyBroadcast, not safe, anyone can access and modify it, Has expired in Android5.0 & API 21, not recommended)
  2. Broadcast usage scenarios: message communication (app internal communication (multi-thread communication), different app communication, system and app communication)
  3. The difference between static registration and dynamic registration: static registration (resident system, not affected by the component life cycle, even if the application exits, the broadcast can still be received, power consumption, memory), dynamic registration (non-resident, follow the life changes of the component, The component ends, the broadcast ends, before the component ends, the broadcast needs to be removed first, otherwise it is easy to cause memory leaks)

ContentProvider

  1. Advantages of ContentProvider: a. Provide a way to share data between applications (address book, weather, etc.); b. Encapsulate and decouple the underlying data storage method, making data operations simple, efficient and safe
  2. ContentProvider, ContentResolver, ContentObserver: ContentProvider (manage data, provide data addition, deletion, modification and query operations, data sources can be databases, files, XML, networks, etc.), ContentResolver (applications can interact with ContentProvider through ContentResolver, different URI operations are different in ContentProvider data), ContentObserver (observe data changes in ContentProvider, and notify the outside world of changes)
  3. URI: Uniform Resource Identifier, Uniform Resource Identifier, uniquely identifies ContentProvider and the data in it, URI is divided into system preset and custom, corresponding to system built-in data (such as address book, schedule, etc.) and custom database respectively. Custom URI: content://com.agg.provider/User/1 (content://: Android specifies the standard URI prefix; com.agg.provider: ContentProvider unique identifier; User: a table name in the database; 1 : Record ID (a record in the table, if not specified, all records will be returned))

Fragment

  1. Life cycle: 6 states (INITIALIZING, CREATED, ACTIVITY_CREATED, STOPPED, STARTED, RESUMED), 11 life cycles (onAttach, onCreate, onCreateView, onActivityCreated (abandoned API, onViewCreated instead), onStart, onResume - onPause, onStop, onDestoryView , onDestory, onDetach)
  2. Communication methods between Fragment and Activity and other Fragments: interface callback, EventBus, shared ViewModel, setArgs of Bundle (when the Activity is rebuilt, the new fragment will be reflected through the empty parameter construction method, and the mArgments will be initialized to the setArgs data of the original Bundle)
  3. FragmentPagerAdapter, FragmentStatePageAdapter: FragmentPagerAdapter (call detach instead of remove, only execute onDestroyView, not onDestroy, will not destroy the Fragment instance, only destroy the View of the Fragment, and the memory will not be released), FragmentStatePageAdapter (call remove when the page is switched, execute onDestroy, directly Destroy Fragment. You can use ViewPager2 and FragmentStateAdapter instead)
  4. Fragment lazy loading: By judging whether the current Fragment is visible to the user, use onHiddenChanged() in add+show+hide mode, and use setUserVisibleHint in ViewPager+Fragment mode. When it is visible and onViewCreated() is called back, it indicates that the View has been loaded. Then call the lazy loading method.

Handler: Mechanism for inter-thread communication

Hander message distribution mechanism

  1. Handler implementation principle: a. Hander sends messages (post, sendMessageDelayed, sendMessageAtTime, enqueueMessage); b. MessageQueue inserts into the message queue (enqueueMessage); c. Looper loops to block and take out messages (prepare, loop, loopOnce, MessageQueue.next); d. Handler processing messages (dispatchMessage, handleMessage)
  2. Sub-thread new Handler: You need to call Looper.prepare to instantiate Looper, and call the loop method to start the loop, and finally you can use the sub-thread new Handler
  3. Handler memory leak: Both non-static inner class and anonymous inner class in java will implicitly hold the external reference of the current class. When the Handler is initialized with the non-static inner class in the Activity, the Handler will hold the reference of the current Activity. There are unprocessed messages in the Handler message queue or when the messages are being processed, the Activity will not be recycled, resulting in memory leaks. Solution: a. Set Handler as a static internal class, and use WeakReference to hold the Activity instance; b. When the Activity life cycle ends, clear the Handler message queue
  4. Message object creation method: a. new Message: each time a new Message is created, go to the heap memory to open up object storage space; b. Message.obtain: first determine whether the message pool is empty, and if it is not empty, take the Message from the header of the message pool Go, and then point the table header to next; if the message pool is empty, it means that no Message has been put into it, then create a new Message object. The message pool is implemented using the Message linked list structure. The default maximum value of the message pool is 50. After the message is distributed and consumed by the handler in the loop, the recovery operation will be performed, and the internal data of the message will be cleared and added to the header of the message linked list; c, handler.obtainMessage (): The obtain() method is also called internally
  5. postDelay execution logic: the time passed in by postDelayed is first summed with the current time SystemClock.uptimeMillis(), and then compared with the execution time of the message head in the current message queue. If it is earlier than the time of the head, it will be used as a new Otherwise, it will traverse backward from the message header to find a suitable position to insert the delayed message. a, postDelay() a 10-second Runnable A, the message enters the queue, MessageQueue calls nativePollOnce() to block, and the Looper blocks; b, followed by post() a Runnable B, the message enters the queue, judging that the time for A has not yet arrived, Blocking, insert B into the head of the message queue (in front of A), and then call the nativeWake() method to wake up the thread; c. After the MessageQueue.next() method is woken up, read the message list again, and the first message B has no Delay, return directly to Looper; d, Looper calls the next() method again after processing the message, MessageQueue continues to read the message list, the second message A has not yet arrived, calculate the remaining time (if there are 9 seconds left) Continue to call nativePollOnce() to block; e, until the blocking time is up or the next time a Message enters the queue
  6. MessageQueue data structure: single-linked list data structure, stored in the order of message to be sent time
  7. Looper, ThreadLocal, and ThreadLocalMap: ThreadLocal is bound to threads. Essentially, ThreadLocalMap in operating threads is used to store local thread variables (sThreadLocal.set(new Looper(quitAllowed))). ThreadLocalMap uses table arrays to store data. ThreadLocal calculates the hash key as the array key, and the array value is the entry internal class (table[key] = new Entry(ThreadLocal, Looper))
  8. Synchronization barrier: In order to allow asynchronous messages to be executed first. a. MessageQueue.next judges that message.target == null is a barrier message, it will filter this synchronous message, and directly loop through to find an asynchronous message to process, so that the priority execution of asynchronous messages can be realized. Before the synchronization barrier is removed, only asynchronous messages will be processed. After all asynchronous messages are processed, it will be blocked; b. Use a synchronization barrier: pass in the async parameter true in the Handler construction method or call setAsynchronous( true); c. Synchronization barrier application: In order to respond to UI refresh events faster in the Android application framework, many places such as draw, requestLayout, and invalidate call ViewRootImpl.scheduleTraversals when View is updated, and use MessageQueue.next synchronization barrier
  9. Sub-thread update UI: Every time the UI is updated, ViewRootImpl.checkThread() checks whether the thread is the creation thread of View. VIewRootImpl has not been created before onResume. At this time, it is also possible to update the UI in the sub-thread, but only the View created by itself can be updated. . Android does not recommend sub-threads to update the UI. If each thread can access the UI, the interface may become chaotic. If they operate on the same resource, it may cause thread safety issues, and locking will reduce performance.
  10. Handler other interview questions: a. A thread can have multiple Handlers, only one Looper object, only one MessageQueue object; b. Looper.loop() source code: for infinite loop, blocked in the next method of the message queue, call after taking out the message msg.target.dispatchMessage(msg) for message distribution; c. MainLooper can be used to create a Handler in the child thread. When Handler handler = new Handler(Looper.getMainLooper()) in the child thread, the Looper and Handler are not in the same thread

HandlerThread

  1. Question: Time-consuming operations are often performed in the project. If threads are often opened and then destroyed, this will undoubtedly consume performance. How to solve it? - thread pool or HandlerThread
  2. Benefits of HanderThread: a. Run the loop in the sub-thread to reduce the pressure on the main thread and make it smoother; b. Open a thread to play the role of multiple threads to perform multiple time-consuming operations without multiple times open thread
  3. Disadvantages of HanderThread: Cannot be concurrent but can only be executed serially, message delay - at this time, thread pool can be used to solve
  4. After the run method finishes running, the thread still survives, because the nativePollOnce of MessageQueue.next will block, waiting for the next message to arrive

IdleHandler

  1. Trigger timing: when the Looper cycle is idle, a mechanism for executing tasks is adopted
  2. Usage scenario: start optimization, want to add other Views that depend on this View after the View is drawn

View

Window

  1. What is Window: a. View carrier (it is a top-level window of a view, which contains View and manages View); b. It is an abstract class (the specific implementation class is PhoneWindow); c. Internally holds DecorView (via Created by WindowManager, and add DecorView through WindowManger)
  2. What is WindowManager: a. It is an interface (inherited from the ViewManager interface with only three methods of adding, deleting and updating. Its implementation class is WindowManagerImpl. WindowManagerImpl implements addView through the WindowManagerGlobal proxy); b. Use WindowManager to add and delete Window (The specific work is handled by WMS, and WindowManager and WMS communicate across processes through Binder)
  3. What is ViewRootImpl: a. It is a bridge between View and WindowManager (ViewRootImpl.setView associates View with WindowManager’s Decorview); b. The three major processes of View are completed through ViewRootImpl; c. All touch screen events, button events, and interface refreshes of Android And other events are distributed through ViewRootImpl
  4. What is DecorView: a. It is a subclass of FrameLayout, which can be considered as the root node view of the Android view tree (View root layout), and Window is bound inside; b. It contains a vertical LinearLayout, which has three parts: upper and lower , the top is a ViewStub delayed loading view (ActionBar is set according to Theme), the middle is the title bar (according to Theme settings, some layouts do not have it), and the bottom is the content bar; c, setContentView is to add the View that needs to be added to DecorView content bar
  5. The relationship between Activity, Window, and View: Activity controls the life cycle and handles events, and holds Window; Window, as the view carrier, is responsible for view control, holding DecorView, which is the root layout of View; View is the view, in Activity.setContentView Add the View view to DecorView in
  6. When is DecorView added to Window by WindowManager: Even though the Activity layout has been successfully added to DecorView, DecorView has not been added to Window at this time. In the handleResumeActivity method of ActivityThread, the Activity.onResume method will be called first, and then the Activity.makeVisible method will be called to complete the addition and display of DecorView in makeVisible()

View drawing

  1. Layout loading process: a. Load the corresponding layout through LayoutInflate.inflate in setContentView; b. In the inflate method, first call Resources.getLayout to load the Xml layout parser into the memory through pull IO; c. createViewFromTag creates View according to the tag reflection of xml to the memory (internally, the onCreatView and createView methods of Factory2 and Factory are used to create Views in the priority order); d. Recursively construct the child Views, and add the child Views to the parent ViewGroup. Performance bottleneck: IO process in layout file parsing; reflection process when creating View objects
  2. 绘制流程-addView流程:ActivityThread.handleResumeActivity——WindowManagerImpl.addView——WindowMangerGlobel.addView——ViewRootImpl.setView——ViewRootImpl.scheduleTraversals——ViewRootImpl.doTraveral——ViewRootImpl.performTraversals
  3. 绘制流程-performTraversals流程:a、performMeasure——DecorView.measure——DecorView.onMeasure——View.measure;b、performLayout——DecorView.layout——DecorView.onLayout——View.layout;c、performDraw——DecorView.draw——DecorView.onDraw——View.draw
  4. Drawing process - Measure, Layout, Draw three major processes: startActivity->ActivityThread.handleLaunchActivity->onCreate ->Complete the creation of DecorView and Activity->handleResumeActivity->onResume()->Add DecorView to WindowManager->ViewRootImpl.performTraversals() Method, measure (measure), layout (layout), draw (draw), traverse the entire View tree from DecorView top to bottom
  5. MeasureSpec: is a static internal class of the View class, used to explain how to measure this View, 32-bit int type, the first 2 bits are the measurement mode SpecMode, and the lower 30 bits indicate the specification size SpecSize in a certain measurement mode
  6. SpecMode: EXACTLY (accurate measurement mode, when the width and height of the view are specified as match_parent or a specific value, it takes effect, indicating that the parent view has determined the exact size of the subview, and the measured value of the View in this mode is the value of SpecSize), AT_MOST (maximum value Measurement mode, which takes effect when the width and height of the view are specified as wrap_content. At this time, the size of the subview can be any size that does not exceed the maximum size allowed by the parent view), UNSPECIFIED (no measurement mode is specified, the parent view does not limit the size of the subview , the subview can be any size you want, usually used inside the system, rarely used in application development)
  7. Activity obtains View width and height timing: a, when onWindowFocusChanged is true; b, view.post() (put the runnable into the RunQueue of ViewRootImpl, and the execution timing is when the next performTraversals arrives, that is, the first time after the view completes the layout Get the width and height); c, ViewTreeObserver.addOnGlobalLayoutListener (when the state of the View tree changes or the visibility of the View inside the View tree changes, the onGlobalLayout method will be called back)
  8. The difference between View.post and Handler.post: When View has been attached to the window, View.post directly calls the implementation of handler; if it is not attached, put the runnable into the RunQueue of ViewRootImpl, RunQueue is executed in the next performTraversals, and MessageQueue is Executed on the next loop
  9. View draws screen refresh: CPU prepares data—passes the data to GPU for rendering through the Driver layer—Display is responsible for consuming display content. CPU (mainly responsible for Measure, Layout, Record, Execute data calculation work), GPU (responsible for Rasterization (rasterization (image expressed in vector graphics format is converted into a bitmap for display)), rendering, after rendering, put it in buffer( image buffer), Display (the screen or display will be refreshed at a certain frame rate, and each time it is refreshed, the image data will be read from the buffer and displayed. If there is no new data in the buffer, it will always be used old data so the screen doesn't appear to have changed)
  10. The difference between View, SurfaceView, TextureView, and SurfaceTexture: View (View is suitable for active updates, while SurfaceView is suitable for passive updates and frequent interface refreshes, such as game screens, cameras or video playback, etc.; View refreshes the page in the main thread , while SurfaceView opens a sub-thread to refresh the page; View does not implement a double buffering mechanism when drawing, SurfaceView implements a double buffering mechanism in the underlying mechanism), SurfaceView (uses a double buffering mechanism (the back buffer accepts data, After the filling is complete, it is exchanged to the front buffer to ensure that the data in the front buffer is complete), and the independent thread has its own Surface for drawing, but the Surface is not in the View hierachy, and its display is not controlled by the attributes of the View. SurfaceView cannot Nested use, and before version 7.0, translation, zoom and other transformations cannot be performed, nor can it be placed in other ViewGroups), TextureView (needs to be used in a hardware-accelerated window, and used like View), SurfaceTexture (different from SurfaceView, it The processing of the image stream is not directly displayed, but is processed by OpenGL, which can be used for secondary processing of image stream data (such as Camera filter, desktop special effects, etc.), GLSurfaceView (different from SurfaceView, it adds EGL's management, with its own rendering thread)
  11. The difference between getWidth and getMeasuredWidth: after onLayout, after onMeasure. getMeasuredWidth (the obtained value is the value set by the setMeasuredDimension method, and its value will be determined after the measure method runs), getWidth (the obtained value is mRight-mLeft among the four parameters passed in the layout method, and its value is in The layout method is determined after running), use (generally use the getMeasuredWidth method in the onLayout method, and use the getWidth method in places other than the onLayout method)
  12. The difference between invalidate, postInvalidate, and requestLayout: invalidate (triggers the onDraw process and is called in the UI thread), postInvalidate (can be called in a non-UI thread, internally sends a message through the Handler to switch the thread back to the UI thread to notify redrawing, and finally calls invalidate) , requestLayout (will trigger the three major processes. It will directly recursively call the parent window requestLayout until ViewRootImpl, and then trigger peformTraversals. Since mLayoutRequested is true, it will cause onMeasure and onLayout (ViewGroup implementation, layout for each subview) to be called. Not necessarily Trigger OnDraw (View implementation, ViewGroup does not need to implement), it will judge whether onDraw is needed according to the flag bit)

Custom View

  1. Steps: Construct-onMeasure(setMeasuredDimession)-onSizeChanged-onLayout-onDraw-provide callback usage. onMeasure (you can not rewrite, if you don't rewrite, you must specify the width and height outside, it is recommended to rewrite), onDraw (rewrite depending on the situation, if you need to draw something), onTouchEvent (also depends on the situation, if you do View that can interact with fingers, just rewrite)
  2. Note: If there are custom layout attributes, the recycle method should be called in time to recycle resources after obtaining the attributes in the construction method; in the onDraw and onTouchEvent methods, avoid creating objects as much as possible, and excessive operations may cause lag
  3. Consider model adaptation: use warp_content and match_parent reasonably. Use RelativeLayout whenever possible. For different models, use different layout files and place them in the corresponding directory, and android will automatically match them. Try to use point 9 images. Use density-independent pixel units dp, sp. Introduce the percentage layout of android. When cutting a picture, cut a picture with a large resolution and apply it to the layout, and it will also have a good display effect on a mobile phone with a small resolution

View event distribution mechanism

  1. Definition: The entire process of passing a click event (MotionEvent) to a specific View & processing
  2. dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent——Activity、ViewGroup、View
  3. View.setOnTouchListener{onTouch}, onTouchEvent, onClickListener relationship: onTouch has the highest priority; the onClick event is triggered by performClick() in the MotionEvent.ACTION_UP event of onTouchEvent
  4. The event first goes to DecorView and then to Window: when the screen is touched, the input system event is distributed from the Native layer to the Framework layer and then to DecorView -> Activity -> PhoneWindow -> DecorView -> ViewGroup of ViewRootImpl
  5. Solve sliding conflicts: external interception method (recommended) - the parent View intercepts onInterceptTouchEvent events as needed; internal interception method - the parent View does not intercept any events, and the child View decides whether to consume events by itself or process them for the parent View according to needs, use If the requestDisallowInterceptTouchEvent method returns true, the onInterceptTouchEvent() of the parent class will not be executed, and the click event can be passed to the following View, depriving the parent view of the right to process events other than ACTION_DOWN. The same: ACTION_DOWN of the parent View in both ways returns false, because an event sequence can only be intercepted and consumed by one View, once an element intercepts this event, all events in the same event sequence will be directly handed over to it for processing ( That is, the interception method of this View will not be called to ask whether it wants to intercept, but the remaining ACTION_MOVE, ACTION_DOWN and other events will be directly handed over to it for processing)
  6. At the same time, set the click method for the parent View and the child View, which one should respond first: respond to the child View first, and the parent view must respond to events first, and must call onInterceptTouchEvent, and then process it in the onTouchEvent of the parent view

RecyclerView

  1. Level 4 cache: mAttachedScrap, mChangedScrap——mCachedViews——ViewCacheExtension——RecycledViewPool. mAttachedScrap/mChangedScrap (on-screen cache, for recycling and reuse when the visible itemView information on the screen changes, notifyItemChanged/rangeChange, if the Holder changes at this time, put it into mChangeScrap, otherwise put it into mAttachScrap), mCachedViews (When the list slides out of the screen, ViewHolder will be cached in mCachedViews, its size is determined by mViewCacheMax, the default is 2, which can be dynamically set by Recyclerview.setItemViewCacheSize()), ViewCacheExtension (you can implement the ViewCacheExtension class yourself to achieve custom caching, you can pass Recyclerview.setViewCacheExtension() setting), RecycledViewPool cache pool (ViewHolder will be cached in mCachedViews first, when the number exceeds (for example, the default is 2), it will be added to RecycledViewPool,
  2. Why put it into mCachedViews first instead of directly into mRecyclerPool. The reason for this: because the itemView that just slid out of the screen may be slid in, so a layer of mCachedViews cache is added, and the holder obtained from mCachedViews is not needed. For re-bind data, the holder taken out by mRecyclerPool will be reset information, re-bind data

WebView

  1. Optimize loading speed: a. Preload WebView; b. Load WebView and request H5 page data at the same time; c. DNS and links are slow, find a way to reuse the domain name and link used by the client; d. Script execution is slow, let the script be at the end Running, without blocking page parsing; e, the back-end processing is slow, the server can be divided into trunk output, and the front-end also loads network static resources at the same time as the back-end calculation
  2. Intermodulation between WebView and JS: Android calls JS (via WebView.loadUrl() or WebView.evaluateJavascript()), JS calls Android (a, through WebView's addJavascriptInterface() for object mapping; b, through WebViewClient's shouldOverrideUrlLoading() method callback Intercept url; c, Android calls back onJsAlert(), onJsConfirm(), onJsPrompt through the following three methods of WebChromeClient, intercept JS dialog boxes respectively, get the message content and then parse it)
  3. Vulnerabilities of WebView: a, arbitrary code execution vulnerability (JS calls Android to perform object mapping through WebView's addJavascriptInterface(), when JS gets the Android object, it can call all methods in this Android object, including system classes (java. lang.Runtime class), so as to execute arbitrary code. Before Android 4.2, it was necessary to intercept prompt() for vulnerability repair, and after 4.2, it was only necessary to annotate the called function with @JavascriptInterface); b. Password plaintext storage vulnerability (solution: WebSettings.setSavePassword(false) closes the password save prompt, and you will not choose to save the password to webview.db); c, domain control vulnerability (for applications that do not need to use the file protocol, disable the file Protocol. setAllowFileAccess(false); setAllowFileAccessFromFileURLs(false); setAllowUniversalAccessFromFileURLs(false); For applications that need to use the file protocol, prohibit the file protocol from loading JavaScript)

animation

  1. Animation classification: view animation (including tween animation (translation, rotation, scaling, transparency) and frame animation), property animation
  2. The difference between tween animation and property animation: a, tween animation can only act on View, and property animation acts on a property & object of View instead of the entire View; b, tween animation does not change the View property (does not change the real position, size, etc.), just change the visual effect; c, single tween animation effect (only simple animation requirements such as translation, rotation, scaling & transparency can be realized)
  3. The difference between ObjectAnimator and ValueAnimator: Both are property animations. ValueAnimator, as the parent class of ObjectAnimator, changes the value first, and then assigns it to the object property, so as to realize the animation operation. The difference is that ValueAnimator is manually assigned to the object property, and ObjectAnimator is automatically assigned give object properties
  4. TimeInterpolator interpolator: Set the change law of the attribute value from the initial value to the end value. Calculates the percentage change of the current property value based on the percentage of time elapsed. Interpolator is responsible for controlling the rate of animation change, so that basic animation effects can change at various rates such as constant speed, acceleration, deceleration, and parabolic speed. Custom interpolator: Calculate the percentage change of the current property value according to the progress of the animation (0%-100%)
  5. TypeEvaluator estimator: Set the specific value of the change of the attribute value from the initial value to the end value. The interpolator determines the change rule and trend of the value, and the next specific change value is handed over to the estimator. Interpolator animations are available, and the estimator is a unique attribute of attribute animation.

Bitmap

  1. Memory usage calculation: load res/raw resource image = width * height * pixel size * scaling factor (dpi); load SD card image = width * height * pixel size
  2. Compression method: width and height compression (Bitmap.createScaledBitmap(bitmap, width, height, true)), scaling method compression (Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)) can be used for Bitmap performs Matrix ratio compression operation according to the image scaling ratio, and sampling rate compression (BItmapFactory.Options setting inJustDecodeBounds only loads the Bitmap boundary width and height information, after setting the value of inSampleSize (int type: take the power of 2), if it is set to n , then the width and height are both 1/n of the original, and the width and height are reduced) and quality compression (Bitmap.compress(Bitmap.CompressFormat.JPEG, quality, ByteArrayOutputStream), options drop from 100, and cycle compression until the memory size is appropriate Position) For File and Resource operations, RGB_565 method (change the memory occupied by a pixel, the default ARGB8888 configuration is used to process the color BItmapFactory.Options set the color mode inPreferredConfig to Bitmap.Config.RGB_565, the memory is reduced by half) https:// blog .csdn.net/Agg_bin/article/details/128026082
  3. 采样率压缩:a、this.inJustDecodeBounds = true;b、BitmapFactory.decodeFile(filePath, this);c、this.inSampleSize = calculateInSampleSize(this, width, height);d、this.inJustDecodeBounds = false;e、BitmapFactory.decodeFile(filePath, this)——(this = BitmapFactory.Options())
  4. Bitmap optimization strategy/design a picture loading library: a. Put high-resolution pictures into corresponding folders (for devices with different densities, place dpi picture resources in corresponding dpi-drawable folders, and use the decodeResource method to adapt according to the screen dpi. In When the image resources are not distinguished by dpi, it is a better choice to place the image resources at a high dpi, which can minimize the chance of OOM); b, image memory compression optimization (quality compression, sampling rate compression); c, do Image cache (three-level cache - memory, disk, network. Memory cache: usually implemented using the least recently used algorithm LruCache; disk cache: the algorithm used is DiskLruCache); d. Timely recycling (bitmap.recycler, using soft references)
  5. Principles of LruCache & DiskLruCache: a. Core idea: When the cache is full, the least recently used cache object will be eliminated first, mainly in 3 steps (initialization, search and addition); b. Algorithm principle: the most recently used The object is stored in LinkedHashMap (array + doubly linked list) with strong references. When the cache is full, the least recently used object is removed from memory, and get (the element will be updated to the head of the queue) and put (the element will be updated) will be provided. Elements are added to the head of the queue, and the trimToSize() method is used to determine whether the cache is full. If it is full, it will be deleted from the end of the queue until the cache size is smaller than the maximum value of the cache) method to complete the acquisition and addition of the cache; c, LruCache is a Generic class, there are two types of caches using the LRU algorithm: LrhCache memory cache and DisLruCache hard disk cache, using the access order (the other is the insertion order) feature of the doubly linked list in LinkedHashMap to implement LRU, that is, the last output of the most recent access
  6. drawable folder loading priority: current density folder - higher density folder - drawable- nodpi folder (it is a density-independent folder, the image system placed here will not automatically scale it, when Only when neither the matching density folder nor the higher density folder can be found will go here to find the picture) - lower density folder (drawable-xhdpi -> drawable-hdpi -> drawable-mdpi -> drawable -ldp)

Binder

Serialization

  1. Serialization: The process of converting memory data objects into binary is called object serialization (Serialization)
  2. Deserialization: The process of restoring a binary stream to a memory data object is called deserialization (Deserialization)
  3. Why do you need to use serialization and deserialization: data objects in memory can only be converted to binary for data persistence and network transmission (memory data objects - serialization into binary - persistence, network transmission - deserialization into memory data objects)
  4. Serializable: Java native serialization is just a sign to identify that a class can be serialized. The Serializable interface has no methods and properties. It is recommended to set the serialVersionUID field value for classes that implement the Serializable interface. Java serialization is not recommended
  5. Parcelable: Write the serialized data into a shared memory, and other processes read the byte stream from this shared memory through Parcel and deserialize it into an object
  6. The difference between Serializable and Parcelable: different storage media (Serializable uses IO to read and write to store on the hard disk, and Parcelable reads and writes directly in memory. Obviously, the memory read and write speed is greater than IO read and write), and the efficiency is different (Serializable requires a lot of IO and reflection operations. Parcelable implements marshalling and unpacking by itself, the operation does not need to use reflection, and the data is also stored in Native memory, which is much faster)
  7. transient: applies only to variables, when serialization is performed, the JVM will ignore the original value of the transient variable and save the default value to the file
  8. serialVersionUID: When deserializing, it not only depends on whether the classpath and function code are consistent, but also depends on whether the serialization IDs of the two classes are consistent
  9. Why it is recommended to display the specified serialVersionUID value: If the class is not modified after writing, there will be no problem. Once the class is modified, the deserialization of the old object will report an error (because if the specified serialVersionUID is not displayed, the JVM will be serialized. Automatically generate a serialVersionUID according to attributes, methods, etc., and then serialize with the attributes, and then perform persistence or network transmission; when deserializing, JVM will automatically generate a new version of serialVersionUID according to attributes, methods, etc., and then use this new version of serialVersionUID Compared with the old serialVersionUID generated during serialization, an InvalidCastException error will be reported when deserialization is performed)
  10. JSON serialization: JSON=JavaScript Object Notation, recommended

What are the IPC communications

  1. The difference between process and thread: process (is an independent unit for resource allocation and scheduling by the system); thread (is the basic unit of CPU scheduling and allocation, does not own system resources, and only temporarily uses some counters, registers, and stacks during runtime. threads share process data)
  2. Multi-process communication problems: a. Static member and singleton mode failure; b. Thread synchronization mechanism failure; c. SharedPreferences reliability is reduced; d. Application is created multiple times
  3. IPC communication methods, usage scenarios, advantages and disadvantages: Intent (4 major components, can only transmit data types supported by Bundle), AIDL (most commonly used, supports one-to-many concurrent real-time communication, pay attention to thread synchronization), Messenger (simplified version of AIDL, Only supports one-to-many serial real-time communication), ContentProvider (constrained AIDL, a large amount of data sharing between processes, mainly CRUD that provides data externally), file sharing (File files, simple data sharing without high concurrency), Socket (network communication, only raw byte streams can be transmitted)
  4. Why doesn't Android use Linux IPC: pipes, message queues, sockets (Socket), semaphores and shared memory. Efficiency, stability and security. Efficiency: The fewer the number of memory copies, the higher the transmission rate. Pipelines, message queues, and sockets need to be copied twice (the data is first copied from the sender buffer to the kernel open buffer, and then copied from the kernel buffer to the receiver. Cache area), Binder 1 copy (receiver cache area and kernel cache area are mapped to the same physical address), shared memory has no copy, Binder's performance is second only to shared memory; stability: but shared memory needs to deal with concurrent synchronization issues , prone to deadlock and resource competition, poor stability. Binder is based on the C/S architecture, and the server side and the client side are relatively independent, and the stability is good. Socket is also based on the C/S architecture, but the transmission efficiency is low and the overhead is high; security: the receiver of the traditional Linux IPC cannot obtain the reliable UID/PID of the other party's process, so it cannot identify the other party's identity; and the Binder mechanism assigns each process UID/PID, and validity detection will be performed according to UID/PID during Binder communication
  5. Why does an application use multiple processes: break through process memory limits, maintain functional stability, isolate risks and avoid main process crashes

What is Binder

  1. From the perspective of inter-process communication, it is an inter-process communication mechanism in Android
  2. From the perspective of the transfer process, it is an object that can be transferred across processes, and the Binder driver will automatically complete the conversion between the proxy object and the local object
  3. From the perspective of Framework, it is the Bridge that connects various Managers (ActivityManager, WindowManager, etc.)
  4. From the perspective of the Android application layer, it is the communication medium between the client and the server, the Binder entity object (Binder class IBinder) in the Server process, and a remote agent of the Binder entity object in the Client process

Binder principle

  1. Core elements: Binder driver, mmap, one copy (come_from_user) + physical address mapping, sending process - come_from_user to kernel buffer area - data receiving buffer area - receiving process user space
  2. Binder cross-process communication mechanism: Based on C/S architecture, it is composed of Client, Server, ServerManager and Binder drivers. The process space is divided into user space and kernel space. User space cannot perform data interaction, but kernel space can perform data interaction. All processes share a kernel space. Client and Server are implemented in user space, while Binder drivers are implemented in kernel space. realized in
  3. Binder principle: a. Create a kernel buffer area: Binder driver uses mmap() to create a kernel buffer area (data receiving buffer area) in the kernel space; b. Realize address mapping relationship: realize kernel buffer area and receive process user space address, and map at the same time to the same physical address; c, send data to the kernel cache area: the sending process copies the data to the kernel cache area of ​​the kernel space through the system call copy_from_user() (data copy once); d, the receiving process receives the data through memory mapping : Since there is a memory mapping between the kernel buffer area and the user space of the receiving process, it is equivalent to sending the data to the user space of the receiving process, thus completing an inter-process communication

Intent size limit

  1. The data carried in the Intent is transferred from the APP process to the AMS process, and then transferred from the AMS process to the target process
  2. When using Intent to transfer data, the Binder mechanism is used, and the data is stored in the Binder transaction buffer, and the transaction buffer has a size limit. Generally, the user process hatched by Zygote, the size of the mapped Binder memory is less than 1M
  3. Therefore, the size of the Intent transmission data is: 1M-8K-packed data (within 1K). ——Affected by the size of shared memory (1M-8K) requested by mmap in binder IPC.

Q: What are the solutions for the large amount of data transferred in Activity jumps?

  1. In-process: singleton mode, static memory, EventBus, Application, SP, File, SQLite, etc.
  2. IPC: MMKV, shared memory ( the use of Android anonymous shared memory - Jianshu opens up memory space through MemoryFile, obtains FileDescriptor; passes FileDescriptor to other processes; writes data to shared memory; reads data from shared memory), Socket or pipe The performance is not so good, involving at least two copies

AIDLCommunication

  1. What is AIDL: AIDL is an interface definition language provided by Android, which simplifies the use of Binder and easily realizes IPC inter-process communication. AIDL will generate a proxy class of the server object, through which the client can indirectly call the method of the server object
  2. AIDL usage steps: a. Write AIDL - create the entity class to be operated, implement the Parcelable interface for serialization/deserialization; create a new aidl folder, create the interface aidl file and the mapping aidl file of the entity class in it; Make project , Generate Binder's Java file. b. Write the server-create a Service, create a generated Stub instance in the Service, and implement the method defined by the interface; return the Binder instance in onBind(). c. Write the client——implement the ServiceConnection interface, and get the AIDL class through asInterface; bindService(); call the operation request defined in the AIDL class.
  3. AIDL key class methods: a, AIDL interface - the interface generated after compiling inherits IInterface; b, Stub - service entity, the implementation class of Binder, the server will generally instantiate a Binder object, and bind it in the server onBind, The client asInterface gets the Stub. This class is automatically generated after compiling the aidl file. It inherits from Binder and is an abstract class that implements the IInterface interface. The subclass needs to implement the specific capabilities that the Server will provide (that is, the method declared in the aidl file); c, Stub.Proxy— —Proxy of the service, the client asInterface obtains Stub.Proxy, and realizes the IInterface interface; d, asInterface——the client passes Person.Stub.asInterface(IBinder) in the ServiceConnection, and returns the Stub according to the same process communication or different process communication () entity or Stub.Proxy() proxy object; e, transact—running on the client side, when the client initiates a remote request, the information will be packaged internally, sent to the server through transact(), and the current thread Suspend, the Binder driver wakes up the Server process and calls onTransact() to process the client request; f, onTransact—running in the Binder thread pool on the server side, onTransact() calls related functions according to the code sent by the Client, and writes the result Enter reply. g. Binder driver - copy the execution result of the target method of the server process to the kernel space of the client process, and notify the client process that the previously suspended thread is awakened and the return result is received.
  4. AIDL supports data structures: eight basic data types, String, CharSequence, List (the receiver must be an ArrayList), Map (the receiver must be a HashMap), classes that implement Parcelable, and AIDL classes
  5. How to optimize the situation where AIDL is used by multiple modules: a. Each business module creates its own AIDL interface and Stub implementation class, and provides its own unique identifier and implementation class to the server; b. The server only needs one Service, and creates The Binder connection pool interface returns the corresponding Binder object according to the characteristics of the business module; c. When the client calls, through the Binder connection pool, the Binder request of each business module is uniformly forwarded to a remote Service for execution, thereby avoiding repeated creation service

performance optimization

ANR

  1. Four major components and four ANR scenarios: Activity (Input Dispatching timeout does not respond to keyboard input, touch screen and other events within 5s); BroadCast (BroadCastQueue TimeOut has not processed the broadcast within the specified time foreground broadcast 10s, background 60s); ContentProvider (ContentProvider TimeOut publish is not completed within 10s); Service (Service TimeOut is not completed within the specified time, the foreground service is 20s, and the background is 200s)
  2. The blocking of the Activity's life cycle callback is not in the scenario that triggers ANR, so it does not directly trigger ANR. It's just that the infinite loop blocks the main thread. If the above four events occur in the system, they cannot be processed within the corresponding time and trigger ANR.

memory optimization

Memory Leak Optimization

  1. What is a memory leak: Long-lived objects hold references to short-lived objects, and short-lived objects cannot be GCed after they are no longer used. For example, if Thread (or Handler) holds the Activity reference for a long time, the Activity and its associated resources and views cannot be recycled.
  2. Reasons for memory leaks: a. Non-static internal classes implicitly hold references to external classes (Handler, Thread); b. Listener and callback are not removed after registration; c. Use Activity context instead of Application context; d. Single The example mode holds the Activity reference and is not released; e. The resource (database, IO, Bitmap) is not closed after use; f. The object held by the static collection class is not released
  3. Reasons for memory overflow: a. The mobile phone has insufficient memory; b. The memory of the app process has reached the upper limit (there are only two reasons - the application memory speed exceeds the GC release memory speed (loading large images, creating a large number of objects in a loop, etc.); memory leaks occur)
  4. Memory leak tools: LeakCanary, Android Studio Profiler
  5. LeakCanary principle: a. Activity calls onDestory and puts it into WeakReference; b. The weak reference is associated with a reference queue ReferenceQueue (after the object associated with the weak reference is recycled, the weak reference will be added to the ReferenceQueue); c. Delay Detect whether there is a current weak reference in the ReferenceQueue within 5 seconds; d. If it is not detected, it means that a leak may occur. Manually call the GC through gcTrigger.runGc(). If there is still no memory leak, it is determined that a memory leak has occurred; e. Then find out the memory leak object The shortest path to GC roots, and the output analysis results are displayed on the page.
  6. Profiler use: After using the App, the Profiler first triggers GC, then dumps the memory snapshot, and then clicks to classify by package, you can quickly view the class remaining in the memory of your App, click on the class to view the corresponding class on the right Instances and reference objects.

image optimization

  1. Reference (View-Bitmap-Bitmap optimization strategy)

Memory optimization in practice

  1. Static memory analysis and optimization: optimization of two large background images on the application homepage (a, RGB565 and quality compression optimization for the guaranteed image and dynamic loading image; b, release of the guaranteed image after the dynamically loaded image returns) or blanking optimization of the carousel background image , The SP is loaded into the memory at one time and saved statically (a, divided into multiple SP files; b, the larger Json string data is migrated to the file or database)
  2. Dynamic memory analysis and optimization: Views that are not necessarily displayed occupy a large amount of memory (use ViewStub for lazy loading), ViewPager memory has not been released (use FragmentStatePagerAdapter instead of FragmentPagerAdapter, only the front and rear pages are kept, not all pages)
  3. Memory jitter optimization: avoid creating objects in loops, establish appropriate cache reuse objects (create objects in onDraw, getView and reuse them as much as possible), and reduce unreasonable object creation

start optimization

  1. Statistical startup time: a, adb shell am start –W package/full path class name, TotalTime is the application startup time; b, Logcat filter Displayed; c, the time from attachBaseContext of Application to onWindowFocusChanged(true) of Activity; d, video capture card
  2. Start-up time-consuming analysis: a, logcat prints the time difference of the code execution segment; b, AOP (Aspect); c, Profiler checks the CPU of the startup process, and sees the specific code time-consuming of the thread
  3. Start optimization scheme: a. Set windowBackground (to achieve fast response and avoid white screen); b. Sub-threads asynchronously initialize Application and main Activity; c. Use directed acyclic graph to sort all tasks and start dependent initialization tasks ;d. Delay execution of tasks (handler delay and use MessageQueue.IdleHandler (execute tasks when the main thread is idle)); e. Optimize the layout of the homepage (reduce hierarchical nesting, use merge, ViewStub, include, dynamic layout); f , Merge part of the network request interface on the home page; g, use local cache to load first

Layout optimization (drawing optimization)

  1. Layout process: mainly includes layout loading process, layout drawing process, layout optimization is mainly optimized from the layout drawing process
  2. Layout analysis tools: a, adb shell dumpsys activity top, view the top activity information, find layout information; b, use Layout Inspector
  3. Layout optimization - reduce the View tree level: a. Use ConstraintLayout for complex layouts; b. Use RelativeLayout without nesting (causing multiple triggers of measure and layout); c. Do not use weight in nested LinearLayout; d. Use merge to reduce a root ViewGroup Hierarchy; e. Use ViewStub to delay loading tags (when the overall layout is inflated, ViewStub will also be parsed but its memory usage is very low, it exists as a placeholder before use, and the inflater operation on ViewStub can only be performed once, and It can only be replaced once)
  4. Layout optimization - avoid overdrawing: a. Remove redundant background; b. Reduce the use of complex shapes; c. Avoid layer overlay; d. Customize View to use clipRect to shield the covered View from drawing
  5. Layout optimization - avoid time-consuming view and data binding: due to time-consuming network requests or complex data processing logic, the binding with the view is not timely, you can use cache, placeholder map, etc.
  6. Layout monitoring: layout loading monitoring (using AspectJ for non-intrusive monitoring for aop), layout drawing monitoring (Choreographer)

Caton optimization (frame rate optimization)

  1. Frame rate detection: a. Look at the approximate degree of lag - adb shell dumpsys gfxinfo package name; b. Look at the exact value - use python script to grab systrace.html, average frame rate (fps/s) = frames/tatol_time (ms /1000 into s)
  2. Caton optimization: a. The performance goal of app development is to maintain 60fps, which means that each frame only takes 16ms≈1000/60 to process all tasks. If an operation takes 20ms, frame loss will occur. If you see the same frame in 32ms, you will feel unsmooth and get stuck; b. The Android system sends a VSYNC signal every 16ms. Stuck optimization is to monitor and analyze what factors cause the rendering task to fail within a vsync time Complete; c. The causes of freezes are intricate, involving code, memory, drawing, IO, CPU (checking code, memory usage, layout drawing, IO operations, CPU usage), etc.
  3. Caton optimization analysis: View systemtrace.html. a. Layout takes time to check the UI thread; b. Transition drawing combines the rendering thread and UI thread; c. Scheduling delay Check the CPU core usage on the frame corresponding to the freeze, pull a piece of CPU usage information, and analyze it in time-consuming order
  4. Caton monitoring: BlockCanary, ANR-WatchDog, single-point problem monitoring

Network Optimization

  1. Network optimization scheme: a. Combine multiple network requests to reduce traffic consumption; b. Cache data returned by network requests; c. Weak network optimization

CPU optimization

security optimization

  1. PIA (Privacy Impact Assessment) Privacy Impact Assessment
  2. SIA: Fireline Scanner, Naga Scanner, Converity Scanner

system start

System startup process

        The Android system architecture is divided into application layer, Framework layer, system runtime layer (Native), and Linux kernel layer. The startup is carried out according to the Android system architecture process (Loader->kernel->Framework->Application)

  1. Bootloader guidance: a, when the power is pressed, the guide chip code starts to execute from ROM; b, the Bootloader guide program copies the operating system image file into RAM, then jumps to its entrance to execute, and starts the Linux kernel; c , The Linux kernel starts, and it will do a series of operations such as setting the cache and loading the driver; d. After the kernel is started, start the init process. As the first system process, the init process converts from the kernel state to the user state
  2. The init process starts: a. fork out of the ServerManager sub-process; b. parse the init.rc configuration file and start the Zygote process
  3. Zygote process start: a, incubate other application processes, all application processes are forked by the zygote process, create new application processes by creating server sockets, and wait for the request of AMS; b, create SystemServer processes (in the Zygote process After startup, the SystemServer process will be forked through the main method of ZygoteInit)
  4. SystemServer process startup: a. Create SystemServiceManager, which is used to create, start and lifecycle manage system services; b. ServerManager.startService starts various system services (WMS/PMS/AMS, etc.), and SystemServiceManager calls ServerManager’s addService to add these The Service service is registered in the ServerManager; c. Start the desktop process so that the user can see the interface of the mobile phone
  5. Launcher process startup: start the system Launcher program to complete the loading and display of the system interface

SystemServer、ServiceManager、SystemServiceManager关系

        Create SystemServiceManager in the SystemServer process. SysytemServiceManager starts some services inherited from SystemService, and registers the Binder of these services to ServiceManager. ServiceManager is the system service manager. For other services inherited from IBinder, add them through the addService method of ServiceManager

  1. SystemServer: It is a process hatched by zygote. The name is system_server, which is called the system service process. Most of the system services provided by Android run in this process, including AMS, WMS, and PMS. The services of these systems are based on a Threads exist in the SysyemServer process
  2. SystemServiceManager: Manage some system services, initialized in SystemServer
  3. ServiceManager: Like a route, the Service registers itself in the ServiceManager, and the client queries the service through the ServiceManager. a. Maintain a svclist list to store service information; b. Provide the proxy of Service to the client, that is, BinderProxy; c. Maintain an infinite loop, constantly check whether there is a service operation request, and if so, read the corresponding kernel binder driver

Why not leave it to SystemServer to incubate the application process, but design a Zygote

  1. The Zygote process is the parent of all Android processes, including system_server and various App processes
  2. Zygote uses the fork() method to generate a new process, and the new process reuses the resources of the Zygote process itself, plus the resources related to the new process to form a new application process. When the application starts, it needs to do a lot of preparatory work, including starting the virtual machine, loading various system resources, etc. These are very time-consuming. If the necessary initialization work can be done in zygote, the sub-process is in It can be shared directly when forking, and the efficiency will be very high
  3. There are a bunch of system services running in SystemServer, which cannot be inherited to the application process

Why does Zygote's IPC communication mechanism use socket instead of binder?

  1. Zygote generates processes through fork, and fork can only copy the current thread, and does not support multi-threaded fork. The process A produced by Zygote fork has only one thread. If Zygote has multiple threads, then process A will lose other threads. At this time deadlock
  2. Binder communication needs to use the Binder thread pool. Binder maintains a thread pool of 16 threads. Process A from fork() cannot use Binder communication.

App start, package, install

Application launch process

        Refer to the four major components - Activity - startup process

Apk Composition

  1. classes.dex: .dex file, the final generated Dalvik bytecode
  2. res: uncompiled resources, the directory where resource files are stored
  3. resources.arsc: compiled binary resource file
  4. AndroidManifest.xml: the program's global manifest configuration file
  5. META-INF: Signature folder, storing signature information

Apk packaging process

  1. AAPT tool: Package resource files through AAPT tool to generate R.java, resources.arsc and res files
  2. AIDL tool: Process AIDL files through AIDL tools and generate corresponding Java interface files
  3. Java Compiler: Compile R.java, Java interface files, and Java source files through Java Compiler to generate .class files
  4. dex command: Through the dex command, the .class file and the .class file in the third-party library are processed to generate classes.dex. This process mainly completes the conversion of Java bytecode into Dalvik bytecode, compresses the constant pool, and clears redundant information, etc. Work
  5. ApkBuilder tool: package dex files, so, compiled resources, original resources, etc. into Apk files through the ApkBuilder tool
  6. Jarsigner tool: use the Jarsigner tool to sign the generated APK file using KeyStore
  7. Resource file alignment to reduce runtime memory

Similarities and differences between assets and res/raw

  1. The same point: the files in these two file directories will be directly packaged into the Apk when packaging the Apk, and will not be compiled into binary
  2. Differences: a. File resources in assets will not be mapped to R, files in res will be mapped to R, and all raw folder resources have corresponding IDs; b. assets may have a deeper directory structure, while res/ There can only be one layer of directories in raw; c. Resource access methods are different. Assets uses AssetsManager, while res/raw directly uses getResource(), openRawResource(R.raw.fileName)

Apk Signing Process

  1. Signature tools: There are two Android application signature tools, jarsigner and signAPK, their signature algorithms are the same, mainly because the files used for signature are different
  2. The difference between jarsigner and signAPK: one is based on the JAR signature method, the other is based on the Apk signature method, jarsigner uses the keystore file (including private key, public key and digital certificate) to sign, apksigner supports the use of keystore files in addition to In addition to signing, it also supports directly specifying the pem certificate file and private key for signing
  3. Signature process: a. Calculation digest (extract the digest of the original data through the Hash algorithm); b. Calculation signature (encrypt the extracted digest through the asymmetric encryption algorithm based on the key (private key), and the encrypted data is signature information); c, write signature (write the signature information into the signature block of the original data)
  4. Verification process: Signature verification occurs during the APK installation process. a. Calculate the digest (first use the same Hash algorithm to extract the digest from the received data); b. Decrypt the signature (use the sender’s public key to decrypt the digital signature to decrypt the original digest); c. Compare the digest ( If the decrypted data is consistent with the extracted abstract, the verification is passed; if the data has been tampered with by a third party, the decrypted data and the abstract will be inconsistent, and the verification fails)
  5. In addition to specifying the keystore file and password, you must also specify the alias and key passwords. This is why: keystore is a keystore, which means it can store multiple pairs of keys and certificates. The keystore password is used to protect the keystore In itself, a pair of key and certificate is distinguished by alias

Apk installation process

  1. Copy the Apk to the /data/app directory, decompress and scan the installation package
  2. The resource manager parses the resource files in the Apk
  3. Parse the AndroidManifest file and create the corresponding application data directory under the /data/data/package name directory
  4. Then optimize the dex file and save it in the dalvik-cache directory
  5. Register the four major component information parsed from the AndroidManifest file into the PackageManagerService
  6. After the installation is complete, send a broadcast


Android

four major components

AMS

Activity

Service

BroadcastReceiver

ContentProvider

Fragment

Handler: Mechanism for inter-thread communication

Hander message distribution mechanism

HandlerThread

IdleHandler

View

Window

View drawing

Custom View

View event distribution mechanism

RecyclerView

WebView

animation

Bitmap

Binder

Serialization

What are the IPC communications

What is Binder

Binder principle

Intent size limit

AIDLCommunication

performance optimization

ANR

memory optimization

start optimization

Layout optimization (drawing optimization)

Caton optimization (frame rate optimization)

Network Optimization

CPU optimization

security optimization

system start

System startup process

SystemServer、ServiceManager、SystemServiceManager关系

Why not leave it to SystemServer to incubate the application process, but design a Zygote

Why does Zygote's IPC communication mechanism use socket instead of binder?

App start, package, install

Application launch process

Apk Composition

Apk packaging process

Similarities and differences between assets and res/raw

Apk Signing Process

Apk installation process


Android development interview series articles:


Guess you like

Origin blog.csdn.net/Agg_bin/article/details/129298627