Summary of Android interview notes, it is recommended to absorb aura~

android message mechanism

The message mechanism refers to how Handler, Looper, MessageQueue, and Message work.

  • Handler is the middleman used to process messages and receive messages. The creation of handler will be accompanied by the generation of looper and MessageQueue in handler. Handler depends on looper, and looper depends on MessageQueue. Therefore, using handler in sub-threads throws exceptions because sub-threads The looper object is not initialized in , and the looper in the main thread has ActivityThreadbeen initialized in , so the Handler can be obtained directly in the main thread.

  • Looper is used to poll messages. To put it bluntly, it implements an infinite loop through the loop method. When there is a message, the message is retrieved through the MessageQueue.next method. When there is no message, the thread is blocked. Get the message when there is a message, and pass the message to the handler. The handler will check whether there is a callback in the message. If there is a callback, it will directly call back, otherwise, it will be processed through handleMessage.

  • MessageQueue is a single-linked list structure to store Messages. Each time a Message is fetched through the next method, after fetching, message.next is given to the current message, and message.next=null is actually removed from the current message. But in the looper, every time the message is taken out in next, it is put into the sPool of the message, which is cached and convenient to use.

  • There is nothing to say about Message. It mainly stores obj and what information that is often used in daily life, as well as target and callback that we don't care about.

The question here is, how many Loopers and Handlers will a thread have, and where will the Looper exist in the thread?

A thread has a Looper, and there can be multiple Handlers. The Looper will be stored in the thread's ThreadLocal object, which is the thread's cache area.

ThreadLocal: It is one-to-one correspondence with the thread, as can be seen from the Thread class, ThreadLocal is used as a Thread variable. ThreadLocal is just a wrapper class of ThreadLocalMap, which implements the get and set methods, and ThreadLocalMap is actually an array composed of Entry internal classes. Entry is inherited from the weak application, and the weak reference is the current ThreadLocal object, and the value of Entry is stored. It is the object to be stored by the current thread, and value is used as a member variable of Entry. ThreadLocal often asks about memory leaks. From the above analysis, it can be found that the ThreadLocal weak reference stored in the Entry object in ThreadLocalMap is directly used as a strong reference of Entry. Therefore, where ThreadLocal is used, to prevent memory leaks, manually call remove method.

IntentService

IntentServiceIt is the Service that Google creates sub-threads on the basis of the original Service. That is to say, IntentService is a service specially provided for android developers that can implement time-consuming operations inside the service. We can onHandleIntentimplement the callback processing of time-consuming operations by rewriting the method, and IntentService will actively destroy itself after the time-consuming operation is completed, and can IntentServicecomplete multiple tasks through multiple startups, but IntentServicewill only be created once. Time will only trigger the onStart method. Internally, it implements the process of Handler asynchronously processing time-consuming operations, and is generally used in services that need to process time-consuming operations.

Question: Why can time-consuming operations be implemented in IntentService?

  • In onCreate, a thread is opened through HandlerThread, and the HandlerThread thread will be different from the Handler we usually use. The looper object is created in the run method, so HandlerThread allows IntentService to use the handler in the child thread to achieve time-consuming operations. .

HandlerThread

HandlerThreadIt is also Thread itself, but the Handler carrier is encapsulated on the basis of Thread, and a looper object is created in the run method, which is why the handler can be used directly in HandlerThread in IntentService. And we know that a thread can have multiple handlers, so it is more convenient to use HandlerThread. We don't need to care about the creation of Handlers. It is generally used to directly process tasks in multithreading.

event distribution

Event distribution is mainly divided into three parts: distribution, interception, and consumption; when we touch the screen, by default, we will go to the distribution of Activity first, then the distribution of ViewGroup, then to the interception of ViewGroup, and then to the distribution event of View, and finally It will be passed to the consumption event of View. If View does not consume, it will be sent back to the consumption event of ViewGroup. If ViewGroup does not consume, it will finally return to the consumption event of View. The entire event distribution forms a U-shaped structure, and the detailed flow of the distribution is summarized below:

  • If the dispatchTouchEvent of the ViewGroup returns true or false, the touch event will not be passed to the child view. If it is false, only action_down will be triggered, and the onTouchEvent event of the ViewGroup will not be triggered. The touch event will be passed to the child view only when super.dispatchTouchEvent is returned.
  • If ViewGroup's onInterceptTouchEvent returns false or super.onInterceptTouchEvent, the touch event will be passed to the child view. Events that return true will not be passed down and handed over to their own ontouchEvent for processing.
  • If the view's dispatchTouchEvent returns true or false, the touch event will not be passed to its own ontouchEvent event. Returning false will only trigger action_down, and move and up will not be triggered; return true to trigger move and up. Return super.dispatchTouchEvent, the touch event will be handed over to its own onTouchEvent processing.
  • If the view's ontouchEvent returns false, there will only be an action_down event, and the touch event will be handed over to the upper layer for processing. If it returns true, it will be consumed, and the event will not be passed upward. If it returns super.ontouchEvent, it depends on whether the clickable returns true.

这里会问到事件冲突的问题?

Events follow a principle, which is to see if he has event consumption. For example, there is a Button in a LinearLayout. Clicking on the LinearLayout will trigger the Button. Here it depends on whether the LinearLayout has a click event. If there is, it will not be passed to the Button. If not, it will be passed to the Button.

Android performance optimization, memory optimization

性能优化: You can start from the interface, apk slimming, confusion, dex subpackage processing, plug-in dynamic loading modules, and cold start when opening the screen

界面优化: You can use include, merge, ViewStub, and constraint layout to start. include can extract public layouts, merge can reduce layout levels, and ViewStub is used to create Views, reducing space occupation and constraint layouts. The level of layout, and secondly, can improve the efficiency of development. In the custom view, pay attention not to initialize the view drawing process, and generally put it in the view initialization method.

apk瘦身: You can use the lint detection tool of android studio to detect resource files, etc.

混淆: It can reduce the file size. This can be tried in practice. After confusion, you can decompile and see the contents of the apk package

dex分包: The main reason is that the structure of the apk package has changed. If the number of methods in the dex package exceeds the maximum number, subpackage processing is required

插件化: Mainly use the idea of ​​dynamic proxy mode and reflection in java, use the android activity to start the process, and dynamically load the activity we need to plug-in through the dynamic proxy mode

开屏冷启动: Open screen cold start is mainly optimized for MultiDex startup. Before 5.0, the dex subpackage is not processed, so you need to use MultiDex.install for compatibility when you want to be compatible with lower versions. And MutiDex.install obtains the dex package in the apk, and then compresses it into a corresponding zip file, and converts the dex file into a DexFile object and a reflection replacement array through reflection. Therefore, the optimization we can do can be done by judging that if the jvm does not support dex subpackage processing, through MutiDex.install for processing, and by monitoring MutiDex.install to start a process activity that monitors MutiDex.install. Wait until the processing of MutiDex.install is completed, and then process the normal logic.

memory optimization

Memory optimization usually refers to memory overflow. The main problem is that the resources that should be released are not reclaimed by the GC processor in time. Usually, the main manifestations are animation, context objects, EventBus, AsycTask, Handler, and singleton Bitmap. What it does is release their unterminated actions, releasing the locked context object.

When the actual project has an mvp architecture, you need to pay attention to the problem of memory leaks. If the p layer holds the instance of the v layer for a long time, it will make it difficult to recycle the objects of the v layer, and the v layer is usually an activity or fragment as an abstraction, so it needs to be in p The layer uses the weak application of the v layer or implements the destruction method of the v layer in the p layer to handle the logic of destruction.

View drawing

activity界面显示流程: After the activity is started, it will not display the view on the interface immediately, but will wait until onResume to actually display the view. First, the windowManager.addView method will be triggered, and the addView method of the proxy object WindowManagerGlobal will be triggered in this method. The proxy viewRootImpl is created in the addView method of the object, and the decorView created in setContentView is placed in viewRootImpl through the setView method of viewRootImpl, and finally the performTraversals method is called through a series of methods of viewRootImpl.

view的绘制: Mainly refers to the onMeasure, onLayout, and onDraw methods of the view. In fact, to understand several methods, you need to trace back to the structure of the interface itself in android. First, the whole is a PhoneWindow object, and then a DecorView, which includes a ViewStub. ToolBar, and then below is a FramLayout, which is the content content in setContentView that we often setContentView in Activity. After talking about the structure of the android interface, let’s talk about how to draw it. The drawing first triggers the onMeasure method of DecorView. Its measurement rules include the width and height of the mobile phone screen, and the measurement mode is MeasureSpec.EXACTLY. So here I understand what the measurement parameters of DecorView (FrameLayout) mean, and then measure the ViewGroup below it. There is a measureChild method in the ViewGroup to measure the child. Here you will ask about several parent layout measurement modes and child Views. Combination of measurement modes:

Measurement mode of ViewGroup MeasureSpec.EXACTLY MeasureSpec.AT_MOST MeasureSpec.UNSPECIFIED
childDimension>0 size=childDimension;mode=EXACTLY size= childDimension;mode=EXACTLY size= childDimension;mode=EXACTLY
childDimension == LayoutParams.MATCH_PARENT size=Viewgroup的size;mode=EXACTLY size=Viewgroup的size;mode=AT_MOST size=Viewgroup的size;mode=UNSPECIFIED
childDimension == LayoutParams.WRAP_CONTENT size=Viewgroup的size;mode=AT_MOST size=Viewgroup的size;mode=AT_MOST size=Viewgroup的size;mode=UNSPECIFIED

After the measurement is processed, the onLayout of the View is followed immediately. The function of onLayout is to fix the position of the View. The parameters passed in by this method are relative to the position of its own parent, and the upper left corner is the coordinate of (0,0). . The last is our onDraw, which is the method we need to draw on the canvas, generally including drawing background, drawing layers and so on.

App startup process

  • From the split of the Linux kernel system to the init process, and a process called Zygote will be started later, and the Zygotecore service process of the system will be split SystemServer, that is, the bottom layer , , etc. SystemServerare included in it . These core services are all started by , that is, we will establish communication with the client through the ipc communication mechanism of binder later .ActivityManagerServicePackageManagerServiceWindowManagerServiceZygote.initActivityManagerServiceActivityThread
  • When we click on the application, Launcherthe application of the system will startActivitystart the application through the method, and Intentthe acquisition will go through the following steps: (1) ActivityManagerServiceIt will PackageManager的resolveIntent()collect the pointing information of this intentobject. (2) Pointer information is stored in an intentobject. (3) The next important step is grantUriPermissionLocked()to verify whether the user has sufficient authority to call the intentobject pointed to by the method Activity. (4) If there is permission, ActivityManagerServiceit will check and start the target in a new task activity. (5) Now, it is time to check whether the process ProcessRecordexists.
  • So if it ProcessRecordis not null, ActivityManagerServicea new process will be created to instantiate it activity.
  • ActivityManagerServiceCall startProcessLocked()the method to create a new process, which will pass the parameters to the Zygote process through the socket channel mentioned earlier. ZygoteIncubate itself, and call ZygoteInit.main()the method to instantiate ActivityThreadthe object and finally return the pid of the new process.
  • Then we are familiar with the ActivityThread.main method to open the message loop through the Looper.prepare and Looper.loop methods
  • Next is the process of creating the Application object. First, the ContextImpl object is created, and then the app process is connected with the Application through the makeApplication method. Here, the Application creation is handed over to the Instrumentation object. In fact, the creation of the activity and the callback of the life cycle are all triggered by it.
  • After the Application is created, it is followed by the familiar Activity. The creation of the activity is also handed over to the Instrumentation object. As mentioned above, the ActivityManagerService will hand over the carried Intent object to the Lanucher application. After a series of operations, the startActivity of the Lanucher will eventually Take the execStartActivity method of Instrumentation, which will request the ActivityManagerService service, and finally pass the information to the client through binder communication, which will eventually trigger the ApplicationThreadscheduleLaunchActivity method of ApplicationThread, which will send the message to the handler object of ActivityThread, and finally hand it over to The Instrumentation object creates an activity. A series of life cycle methods will be triggered later.

Principle of Eventbus

EventBus是一款在android开发中使用的发布/订阅事件的总线框架,基于观察者模式,将事件的接收者和发送者分开,基本包括了如下几个步骤:

注册事件的订阅方法: This step is mainly to find out which methods under the subscriber need to be subscribed 订阅操作: store the methods that need to be subscribed in a data structure similar to HashMap, which is convenient for later use when releasing resources such as sending events and canceling registration: this 发送事件step First traverse the event queue, then take out the event from the queue, and remove the event from the queue. After getting the event, determine which thread the event is in. If it is a non-UI thread, you need Handler to process it. If so, directly Invoke the observed method via reflection. 反注册: There is nothing to say about this step. It is mainly to remove the subscribed method stored in the HashMap above and release the resources in the memory.

What are the operators of Rxjava, and talk about their functions

just: Put the same data source combination on the observed object

from: Put data sources like arrays and collections on the observer

map: Transform one data source into another

flatmap: Transform a data source into another data, and the transformed data is arranged in random order

concatmap: Transform a data source into another data, and the converted data is sorted according to the order of the previous data source

toList: Convert the form of an array into a List collection

subscribeOn: Set the thread where the Observable's call method is located, that is, the thread of the data source

observeOn: Set the thread where the call method of subscribe is located, that is, the thread of data processing

filter: Filter data in the data layer of the observed

onErrorResumeNext: When an error occurs, you can specify the observer when the error occurs

retryWhen: When an error occurs, go through the process of being subscribed again

concat: Merge the same type of observed objects into one observed object, which is a bit like collection and array splicing data.

zip: Handle the data transmission of multiple different result sets. Generally, it is more commonly used to combine multiple network requests and then process business logic in a unified manner. There are still many operators to see by yourself, these operators are enough for interview.

What is the difference between the thread lock method and the class object?

线程锁锁方法: You need to wait until the thread runs out of this method to release the synchronization lock 线程锁锁类对象: You need to wait until the thread runs out of this type of object to release the synchronization lock 区别: the area of ​​​​the lock method requires a small lock class object to include all attributes of the class

Principle of AsyncTask

AsyncTask is mainly the encapsulation of the java thread pool in android. Two thread pools are enabled by default in this class. One thread pool is responsible for queuing tasks to ensure that tasks are processed individually. The other thread pool is used to process tasks exclusively. After the task is processed, it is handed over to the Handler to send a message to the main thread, and then the Handler processes the thread and handed it over to onPostExecutethe method.

内部过程:

  • The AsyncTask initialization phase creates WorkerRunnablean object, which is doInBackgroundthe Callable object to be processed, and then creates FutureTaskan object, which WorkerRunnablewraps the above layer Runnableand Futureobject. In fact, the task to be performed by the thread pool is this WorkerRunnableobject.
  • In the process of executing tasks, SerialExecutorobjects are queued for processing FutureTask, which ArrayDequeare retrieved in order through objects FutureTask, and then handed over to THREAD_POOL_EXECUTORobjects. It is a thread pool created in a static code block, so it THREAD_POOL_EXECUTORis the key to actually executing tasks.
  • After execution, all that remains is that the Handler of the main thread sends the message to the main thread for processing.

问题:

  • Will AsyncTask create a thread pool inside?

    Two thread pools, one thread pool is responsible for queuing and processing tasks; the other thread pool is used for processing FutureTask, which is to WorkerRunnablewrap Runnablethe object with a layer above.

  • What happens if AsyncTask executes the execute method on this?

    Throw directly IllegalStateException(illegal state exception)

Talk about the characteristics of MVP and MVVM

MVP: It mainly separates the codes of the M layer and the V layer, establishes their association through the P layer, and realizes the decoupling of the M layer and the V layer. The disadvantage is that every time a function is added, the corresponding interface callback needs to be added. No way, the core of MVP is to achieve isolation through the interface, and hand over the relevant business layer to the P layer.

If you want to elaborate on mvp, you need to pay attention to a few points:

  • The logic of the p layer handles a single function, do not integrate the entire function of adding, deleting, modifying and checking under one module.
  • Since the p layer holds the reference of the v layer, usually a weak reference is used to hold the view layer instance in the p layer, and the reference of the v layer needs to be destroyed when the p layer is destroyed.
  • The interface classes of the p-layer and v-layer referred to by the conforming class are placed in a contract interface class. The conforming class is convenient for managing the functions of the business layer, and a single function is placed in a contract conforming class. For example, we have a function to add bookshelves:
public interface AddBookShelfContract {
    interface View extends BaseContract.BaseView {
        void addBookShelfSuccess(BookShelfItem... bookShelfItem);

        void addBookShelfFail();

        void alreadyBookShelf(BookShelfItem bookShelfItem);
    }

    interface Presenter extends BaseContract.BasePresenter<View> {
        void addBookShelf(String tokenId, BookShelfItem... bookShelfItem);
    }
}

MVVM: It mainly uses the observer mode to notify the corresponding View change process through data changes. The M layer is the same as the M layer in the above MVP. It is implemented by network request + data cache. The double V inside is implemented by the ViewModel, and the other AndroidDataBinding implements the V layer, which is obtained by the ViewModel layer. After the data of the M layer, notify the AndroidDataBinding of the change on the UI through the observer mode. If there are shortcomings, I can only complain about AndroidDataBinding. When writing logic in xml, there is no hint code at all. It feels like writing js. The readability must be a bit difficult for beginners.

What are the observer patterns used in android

Observer mode is composed of a sender (the sender is the author's own name, which is much more appropriate than the observed) and an observer. The sender takes the initiative when the state changes (user operation, program active change, etc.) Notify all observers to refresh accordingly. The most classic example in android is to say that the data source of ListView has changed, and the list is refreshed. When settingAdapter, generate one AdapterDataSetObserver, and then subscribe to the observer. onChangeThere is a method in the observer method requestLayout, which is the method that triggers the UI to change. In BaseAdapterit, you can see notifyDataSetChangedthat what is actually triggered is the method DataSetObservableof the observer notifyChanged, the method that notifyChangedwill be AdapterDataSetObservertriggered onChange. So in the end, the listView will be taken requestLayout, and the UI will be refreshed at last.

Talk about Google's new Lifecycle framework

Hand over the life cycle method of the class to Lifecycle for management, realize the monitoring of the life cycle of the class, and process the logic code of the life cycle in Lifecycle. Here are several objects involved: LifecycleObserver接口(Lifecycle Observer): The class that implements this interface can be registered by the addObserver(LifecycleObserver o) method of the LifecycleOwner class through annotations. After being registered, LifecycleObserver can observe the life of LifecycleOwner periodic events. LifecycleOwner接口(Lifecycle holder): The class that implements this interface holds the life cycle (Lifecycle object), and the change of the life cycle (Lifecycle object) of the interface will be observed by its registered observer LifecycleObserver and trigger its corresponding event. Lifecycle(Lifecycle): Unlike LifecycleOwner, LifecycleOwner itself holds Lifecycle objects, and LifecycleOwner obtains internal Lifecycle objects through its Lifecycle getLifecycle() interface. State(The state of the current life cycle): several event states. Event(The event corresponding to the change of the current lifecycle): When the Lifecycle changes, the callback event of the event state.

okhttp principle

Okhttp mainly implements asynchronous and synchronous network operations, and creates different callobjects. The call objects here are runnable objects one by one. Since we have many tasks, there is a Dispatcherthread pool wrapped here to handle different ones call. Among them, Three kinds of queues are created in the class, which are used to store the asynchronous tasks being executed, synchronous queues, and prepared queues. Finally, when each task is executed, the first-in-first-out principle of the queue is adopted to process each task, which is handed over to various interceptors behind for processing, including request-prepared interceptors, cache interceptors, and network connections. Interceptors, each interceptor forms a chain of responsibility. responseReturn information to the end . The bottom layer of OkHttp is to send HTTP requests and receive responses through Java Socket (this is also easy to understand, HTTP is based on the TCP protocol), but OkHttp implements the concept of connection pool, that is, multiple requests for the same host can actually be shared A Socket connection, instead of closing the underlying Socket every time an HTTP request is sent, realizes the concept of a connection pool. OkHttp encapsulates the OkIo library used for Socket read and write operations.

Principle of Retrofit

Retrofit is encapsulated into a RESTFUL network request framework based on okHttp, configures various parameters through the factory mode, and realizes network requests through dynamic proxy and annotation. Retrofit utilizes the factory model and will be divided into production network request executor (callFactory), callback method executor (callbackExecutor), network request adapter (CallAdapterFactory), data converter (converterFactory) and other factories. callFactory is responsible for producing okHttp calls. Everyone knows that okHttp completes synchronous and asynchronous http requests by generating call objects.

The callbackExecutor generates the data callback executor corresponding to the platform by judging different platforms. The callback executor on the android side calls back data through the handler.

CallAdapterFactory is a data analysis factory. Generally, we can configure the json data analysis adapter.

converterFactory is a factory for data conversion. Generally, we can configure the data conversion of Rxjava.

Retrofit implements annotations of interface class configuration through dynamic proxy mode, parses parameters into HTTP objects, and finally implements network requests through okHttp.

RxJava's thread switching principle

  • RxJava subscribeOnspecifies the thread on which the observer occurs by observeOnspecifying the thread on which the observer occurs. Which Schedulers.IO generates is IoScheduler. In the process of subscribing between the observer and the observed, subscribeActualthe method of the observed will be triggered first. In this method, you can see the method that will eventually go scheduler, scheduleso the method mentioned above IoScheduleris actually the method that calls it schedule, and it will eventually Objects NewThreadWorkerare generated in it ScheduledExecutorService, but ScheduledExecutorServiceactually ScheduledThreadPoolExecutora core thread is created by the thread pool with the maximum number of threads being Integer.MAX_VALUE. Eventually, the Runnable object will be executed by the or ScheduledThreadPoolExecutormethod , and the Runnable executes the method of the observer. So it is explained that the method of the observer is executed in the child thread.submitschedulesubscribesubscribe

  • observeOnIt is the thread generated by the observer, which AndroidSchedulers.mainThread()is actually HandlerScheduleran object. In the observer part, the final observation part will use the Scheduler scheduleDirectmethod, and HandlerSchedulerthis method wraps an ScheduledRunnableobject, and processes the runnable object through the handler.postDelayed of the main thread.

RecyclerView source code, cache analysis

RecyclerView uses a powerful division of labor. The display and typesetting are handled by LayoutManager, the data display is handled by adapter, the item is dynamically added and drawn by ItemDecoration, and the animation of item is handled by ItemAnimator. The interview mainly analyzes the recyclerView cache. The recyclerView cache is maintained by the internal class Recycler. Among them, the first-level cache contains the mAttachedScrapcache of the viewHolder currently displayed on the current screen. The second-level cache is the one mCachedViewsthat is placed outside the screen. The viewHolder cache mRecyclerPoolis the three-level cache of recyclerView. It is generally used when RecyclerView is nested with RecyclerView. For example, there is RecyclerView in the item of the outer RecyclerView, then the inner RecyclerView reduces the inner RecyclerView by sharing the RecyclerPool of the outer RecyclerView. ViewHolder creation.

Binder mechanism

The binder mechanism is the cornerstone of inter-process communication on the android side. Using aidl's IPC communication method, we can use it to define the interface for two processes to communicate with each other. It is an inter-thread communication mechanism based on Service. Its essence is C/S architecture, which requires a server and a client. There are four objects in the AIDL communication method, one is IInterface, which is specially used to schedule the interface, Stub is used to respond to the communication and send data to the service end, and Proxy is responsible for the packaging of the communication between the two processes, which can be regarded as the packaging of the indirect call to the Stub class, service is the key class for the server to process data. Use a graph to represent the following:


The full version of the interview notes is far more than that. After all, it took about two weeks to sort out, and I also consulted a lot of reference learning documents. The corresponding reference answers that I guessed are shown here. For a small part of the content, if you want to refer to the complete works, you can →:https://qr18.cn/CgxrRy

Guess you like

Origin blog.csdn.net/weixin_61845324/article/details/130435994