preface

If your layout is slow to load, or you have some ideas of your own. Then this AsyncLayoutInflater asynchronous loading layout is worth having.

Api usage

It’s easy to use, just pass a context, a layout ID, a callback, and then set the view in the callback, and that’s it. The specific usage is as follows:

class AsyncLayoutInflaterActivity : AppCompatActivity(a){
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Load the layout asynchronously
        AsyncLayoutInflater(this).inflate(R.layout.activity_async_layout_inflater,null)
        { view: View, i: Int, viewGroup: ViewGroup? ->
             // Load the layout asynchronously
            setContentView(view)
        }
    }
}
Copy the code

Analyze the source code from the entry

     @UiThread
    public void inflate(@LayoutRes int resid, @Nullable ViewGroup parent,
                        @NonNull AsyncLayoutInflater.OnInflateFinishedListener callback) {
        if (callback == null) {
            throw new NullPointerException("callback argument may not be null!");
        }
        AsyncLayoutInflater.InflateRequest request = mInflateThread.obtainRequest();
        request.inflater = this;
        request.resid = resid;
        request.parent = parent;
        request.callback = callback;
        mInflateThread.enqueue(request);
    }

Copy the code

It’s important to note that these are these two lines of code

AsyncLayoutInflater.InflateRequest request = mInflateThread.obtainRequest();

mInflateThread.enqueue(request);

Let’s break it down sentence by sentence!

AsyncLayoutInflater.InflateRequest request = mInflateThread.obtainRequest();

InflateRequest = InflateRequest = InflateRequest = InflateRequest = InflateRequest = InflateRequest = InflateRequest = InflateRequest Object caching reduces the cost of creating objects. Object cache pools are used everywhere. It can be reused by subsequent applications to reduce the number of objects created and released, thus improving application performance.

mInflateThread.enqueue(request);

In this case, start a thread, asynchronously, in an infinite loop to fetch the layout resolution task, and block without it.

Let’s move on to the core layout resolution task, runInner(), which will be executed in an infinite loop, request = mqueue.take (); Unblock a task that is unblocked from the queue may be handed over to LayoutInflater.inflate, creating a View. Here’s a little detail that I’ll talk about in a minute. After the view is generated, it sends a handle message to notify you.

public void runInner() { AsyncLayoutInflater.InflateRequest request; try { request = mQueue.take(); } catch (InterruptedException ex) {return; } the try {/ / generated view request. View = request. The inflater. MInflater. Inflate (request. Resid, request. The parent, false); {}} the catch (RuntimeException ex) / / send a handle Message Message. Obtain (request. Inflater. MHandler, 0, the request). SendToTarget (); }Copy the code

Let’s move on to the code for the Handle Callback.

Let’s see, there is a small fault tolerance mechanism that inflate the view by calling it uninflate. Then back to transfer into the mouth OnInflateFinishedListener, then call mInflateThread. ReleaseRequest (request); Releasing the object into the cache pool completes the process.

But one thing to notice is that this is not a child thread, it’s a UI thread.

And that brings us to the end.

private Callback mHandlerCallback = new Callback() { @Override public boolean handleMessage(Message msg) { AsyncLayoutInflater.InflateRequest request = (AsyncLayoutInflater.InflateRequest) msg.obj; // If the view is empty, {request.view = Minflater.inflate (request.resid, request.parent, false); } request.callback.onInflateFinished( request.view, request.resid, request.parent); mInflateThread.releaseRequest(request); return true; }};Copy the code

Let me look at the overall flow chart

Small detail analysis

Let’s get into the finer details of generating a view. BasicInflater extends from LayoutInflater, and when parsing XML asynchronously, the native layout calls back here. And we’re going to go back to the createViewFromTag method in the LayoutInflater source code and say this. The following

If (-1 == name.indexof ('.')) {// Native layout view = onCreateView(context, parent, name, attrs); } else {// custom view = createView(context, name, null, attrs); }Copy the code

Now let’s look at the core code of BasicInflater’s onCreateView. Here I get a whiff of tanuki, and we can just add our own code to the front. Replace it with our view and the skin function will be implemented.

@Override protected View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException { for (String prefix : SClassPrefixList) {try {// Go to "android.widget.",android.webkit.",android.app first. Look for // because most of the layouts are in there like Button editText. Android.widget.textview // But why not use an accurate hit here? For example, we know that TextView is under Android.Widget. View view = createView(name, prefix, attrs); if (view ! = null) { return view; }} catch (ClassNotFoundException e) {}} return super.onCreateView(name, attrs); }}Copy the code

For example, if you add the following code in front of it, wouldn’t it be possible to replace your own view?

  if(name.equals("TextView")){
    return createView("MyTextView","com.diy.view.", attrs);
   }
Copy the code

“Android.widget.”, Android.webkit.”,android.app will be prioritized in onCreateView. Look it up, because that’s where most of the layout is. Button, EditText. Android.widget. Textview. If it hits, it returns to view.

But why don’t you use a good shot here? For example, we know that TextView is under Android.Widget. Can I get you some answers?

Check out my article about the article object cache pool

Source analysis of the Pools object cache pool in the Android layout asynchronous loading

Blocking is mentioned in the article, which can also be learned from my article. You can slide to the center to see why blocking does not occupy resources, which is explained in the center.

Call the thread’s start(), does the thread really execute right away?

Interviewer: Let me hand Handle it

conclusion

One day an article, write write already do not know what to write, only to find their own ignorance and lack of knowledge.

My knowledge is limited, if there is a description of the error, look tiger is.

Look at thisLike you owe me a thumbs up.

Thank you very much. Your praise is like the sun in winter.