Tags

, , , , ,

Not always we can be satisfied with the default views that any OS gives. To incorporate our own design elements and to reuse them, we need some control over them as custom views. Android provides the ability to create custom views. However, there is a secret for optimizing.

Every view is created through LayoutInflater. Let’s take a quick look into it’s code.

// As per: https://github.com/android/platform_frameworks_base/blob/master/core/java/android/view/LayoutInflater.java
View view;
if (mFactory2 != null) view = mFactory2.onCreateView(parent, name, mContext, attrs);
else if (mFactory != null) view = mFactory.onCreateView(name, mContext, attrs);
else view = null;

if (view == null && mPrivateFactory != null) {
    view = mPrivateFactory.onCreateView(parent, name, mContext, attrs);
}
            
if (view == null) {
    if (-1 == name.indexOf('.')) {
        view = onCreateView(parent, name, attrs);
    } else {
        view = createView(name, null, attrs);
    }
}

As we can see, it tries to use any defined factory for creating views. If there are no factories set up, it tries to see if it’s a stand Android widget. If that too fails, it tries to create the class based on the name provided (not shown above). This operation is costly. Why not we just supply a factory for Android to use?

public final class MyViewsFactory implements LayoutInflater.Factory {
    @Override
    public View onCreateView(String name, Context context, AttributeSet attrs) {
        if (TextUtils.equals(viewName, "com.mycompany.myproject.CustomView"))
            return new CustomView(context, attrs);
        else
            return null;
    }
}

Now the view is created using the factory, instead of doing a long search. It’s better to create a singleton class and use it in a call to setFactory() from the Activity — before calling setContentView().

public final class MyActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        // Set the factory for the views used.
        // Note: MyViewFactory shown above is not singleton yet!
        LayoutInflater.from(this).setFactory(MyViewsFactory.getInstance());

        super.onCreate(savedInstanceState);
        setContentView(R.layout.some_layout);
    }
}

Is that all? No! Now that we return a View for the XML string, do we still need a long name like com.mycompany.myproject.CustomView? Definitely not! We can just use CustomView or SmallNameForView or anything else in XML markups, and supply the related view ourselves.

About these ads