It’s too long to read. Go straight to the summary

As we all know, in Android, the Activity loading layout is commonly used in the following ways:

setContentView(View view)    
setContentView(@LayoutRes int layoutResID)
Copy the code

A View can be loaded in the following ways:

View.inflate(Context context, @LayoutRes int resource, ViewGroup root)
LayoutInflater.from(Context context).inflate(@LayoutRes int resource, @Nullable ViewGroup root)
LayoutInflater.from(Context context).inflate(XmlPullParser parser, @Nullable ViewGroup root)
Copy the code

Because of Android’s special mechanism, files in assets and raw are not compiled (that is, they cannot be accessed through R.XXX. ID), So you can only access the XML layout with the LayoutInflater. From (Context Context).inflate(XmlPullParser Parser, @Nullable ViewGroup root) method.

So let’s look at how to get the XmlPullParset object, the AssetManager object from context.assets, AssetManager, on the other hand, can obtain an XmlResourceParser object via openXmlResourceParser(@nonnull String fileName).

So we can get the following code from the above analysis:

    fun getView(ctx: Context, filename: String): View? {
        return LayoutInflater.from(ctx).inflate(am.openXmlResourceParser(filename), null)
    }
Copy the code

1. When we write the demo and run it, we will encounter the first pit:

The program threw a FileNotFoundException exception

java.io.FileNotFoundException: activity_main.xml
Copy the code

You look up the files and see that you have to prefix the file names with “assets/”

2. When you modify your code, you need to judge the file prefix

fun getView(ctx: Context, filename: String): View? { var name = filename if(! filename.startsWith("assets/")){ name = "assets/$filename" } return LayoutInflater.from(ctx).inflate(am.openXmlResourceParser(name), null) }Copy the code

After changing the code, you start a second wave of tests, only to find that the program throws another exception:

java.io.FileNotFoundException: Corrupt XML binary file
Copy the code

This error indicates that your XML layout file is in the wrong format. The XML file placed in assets should be the compiled file (i.e., the XML file in APK) as shown below:

3. You copy the layout/activity_main. XML in your APK to the assets directory of your project and start the third test:

You find that even though you can get the ViewGroup that corresponds to the layout, you can’t get the subview using the findViewById(ID) method, so you start looking at the source code of the ViewGroup. You were smart enough to discover the following:

public final <T extends View> T findViewWithTag(Object tag) {
        if (tag == null) {
            return null;
        }
        return findViewWithTagTraversal(tag);
    }
Copy the code

This method can be set by the tag, to get the corresponding child View

4. So, after you set the tags in the XML for the child View, you write the code and start the fourth wave of testingWhen you look at the APP on your phone, you see that the characters displayed in textView have changed:

Into the pit guide

  1. Java. IO. FileNotFoundException: activity_main. XML layout XML file name to the prefix “assets/”

  2. Java. IO. FileNotFoundException: Corrupt binary XML file XML layout files need to be put in the compiled XML, if just plain XML files, you don’t need to

  3. Set the tag for the child View in XML, and get the child View through the findViewWithTag(Tag) method of ViewGroup

  4. Use the HTML page “file:/// android_asset/codefilename “filename as the file path in assets directory

Tool class source:

package com.coding.am_demo import android.content.Context import android.content.res.AssetManager import android.graphics.Bitmap import android.graphics.BitmapFactory import android.view.LayoutInflater import android.view.View import java.io.IOException /** * @author: Coding.He * @date: 2020/10/9 * @emil: [email protected] * @des: Obtain assets from assets */ object AssetsTools {private Lateinit var am: AssetManager private Lateinit var appCtx: Context /** * Initialize AssetsTools ** / fun init(CTX: Context) {this. AppCtx = CTX. ApplicationContext am = CTX. ApplicationContext. Assets} / * * * for XML layout * need to assets directory. XML is the end  * */ @Throws(IOException::class) fun getView(filename: String): View? { if (! filename.endsWith(".xml")) return null val name = when { filename.startsWith("assets/") -> filename else -> "assets/$filename" } return LayoutInflater.from(appCtx).inflate(am.openXmlResourceParser(name), Null)} /** * getBitmap(filename: String): Bitmap? Bitmap? = null try { val ins = am.open(filename) ins.use { bitmap = BitmapFactory.decodeStream(ins) } } catch (e: IOException) {e.printStackTrace()} return bitmap} /** * Get HTML path in assets ** / fun getHtmlUrl(filename: String):String{ return "file:///android_asset/$filename" } }Copy the code

Demo Project Address