zero

Typedarray what is Typedarray for

When writing XML for interface layouts, we often set component properties, such as common ones

android:id="@+id/id_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
Copy the code

What if we need to add custom properties to our custom views, viewGroups, and so on? You just need typeDarray. This time our example is to add attributes to a custom View.

How to use Typedarray

1. Prepare a custom view

Code warning

public class ViewWithAttrs extends View { public ViewWithAttrs(Context context, AttributeSet attrs){ super(context, attrs); }}Copy the code

2. Prepare an arrts. XML file

<resources>
    <declare-styleable name="ViewWithAttrs">
        <attr name="paint_color" format="color"/>
    </declare-styleable>
</resources>
Copy the code

Note that on the second line name=”ViewWithAttrs”, name is the component to which you want to add attributes, and it must have the same name as view.

Now it’s time to add the property we want, so here I’ve added a property, the name of the property is “paint_color”, this is my own definition, and the property type is :color.

There are other optional types:

Reference C. Reference a resource ID String Indicates a character string. Color indicates a color value. Dimension indicates a size value. Boolean Indicates a Boolean value Representation bit operation

Typedarray fetch attributes in XML

Typedarray is created using Contex’s obtainStyledAttributes method, and the corresponding attributes are obtained using getXXX.

show me the code

public class ViewWithAttrs extends View { private Paint mPaint; public ViewWithAttrs(Context context, AttributeSet attrs){ super(context, attrs); mPaint = new Paint(); mPaint.setStyle(Paint.Style.STROKE); mPaint.setAntiAlias(true); // Obtain TypeDarRay TypeDarRay = by obtainStyledAttributes method context.obtainStyledAttributes(attrs,R.styleable.ViewWithAttrs); / / use typedarray to obtain the corresponding attribute int paintColor = typedarray. GetColor (R.s tyleable ViewWithAttrs_paint_color, Color. BLACK); // The last color. BLACK is the default value mPaint. SetColor (paintColor); typedArray.recycle(); // Don't forget to recycle! }}Copy the code

So now we have the property we want, and we can use it in this View

@Override protected void onDraw(Canvas canvas){ super.onDraw(canvas); Canvas. Methods like drawCircle (200200, 50, mPaint); }Copy the code

4. Wait, we haven’t set the properties yet

Add our View and set the properties in the MainActivity layout file activity_main.xml

<com.idealcountry.test.ViewWithAttrs
        android:id="@+id/id_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:paint_color="@color/blue"/>
Copy the code

So we can get the PAINt_color set by the XML in our code. // Here I registered a color in color.xml: color/blue

Results:

Three, a final thought

The problem of AttributeSet

When writing a custom View, I first defined a class attribute to hold the Typedarray obtained from AttributeSet, but I slipped and wrote the typeDarray in the onDraw() method. When testing the View, I found that I failed to obtain the attributes defined in XML. Debug shows that the value obtained in the onDraw method is null and the default value is used. But why?

Instead of assigning an AttributeSet to each View, it has a caching mechanism. It’s common, so if you go to Ondraw, it’s possible to get an AttributeSet that you don’t need.

Typedarray recovery? There is no the

Why the emphasis on recycling? It’s not like it’s hogging the thread, so what if I don’t recycle it? (In fact, if you do not recycle, AS will always bother you, saying that you do not recycle)

To find out, we need to get into the source code and take a look. Several goto declarations, which we eventually find in TypeDarray.java, note the first sentence in this static method.

static TypedArray obtain(Resources res, int len) {
        TypedArray attrs = res.mTypedArrayPool.acquire();
        if (attrs == null) {
            attrs = new TypedArray(res);
        }

        attrs.mRecycled = false;
        // Reset the assets, which may have changed due to configuration changes
        // or further resource loading.
        attrs.mAssets = res.getAssets();
        attrs.mMetrics = res.getDisplayMetrics();
        attrs.resize(len);
        return attrs;
    }
Copy the code

And the constructor of this class is hidden, it’s protected, it’s obviously a singleton pattern.

   /** @hide */
    protected TypedArray(Resources resources) {
        mResources = resources;
        mMetrics = mResources.getDisplayMetrics();
        mAssets = mResources.getAssets();
    }
Copy the code

That makes it clear that typedarray is obtained from a pool of Typedarray in the static method Typedarray.obtain. We use TypeDarray in the View, and the view creates as the activity creates, so we can’t always create a New TypeDarray every time, so we use typeDarray pool to manage. This is the official has been stressed, after use to flush, ah no, after use must be recycled.

O did a quick sort K

// As a beginner in Android development, if I have any mistakes or shortcomings, please point them out. I hope to make progress together with you