Augusto Carmo Augusto Carmo - 26 days ago 11
Android Question

Custom compound view and .findViewById()

I am really worried about the

.findViewById()
method and its use in a custom compound view creation. I am not sure about the exact place that it is guaranteed that it will never return
null
.

Let's say I have this custom compound view and that it is added to some
.xml
like this:

<com.app.path.TwoButtonsView
android:id="@+id/ok_cancel_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>


two_buttons_view.xml
:

<?xml version="1.0" encoding="utf-8"?>
<merge>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">

<TextView
android:id="@+id/first_button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:clickable="true"
android:gravity="center"
android:textAllCaps="true"/>

<TextView
android:id="@+id/second_button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:clickable="true"
android:gravity="center"
android:textAllCaps="true"/>
</LinearLayout>
</merge>


TwoButtonsView.java


public class TwoButtonsView extends LinearLayout {

// views
private TextView mFirstButtonView;
private TextView mSecondButtonView;

public TwoButtonsView(Context context) {
super(context);
init(context, null);
}

public TwoButtonsView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}

public TwoButtonsView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public TwoButtonsView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}

private void init(Context context, AttributeSet attrs) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.two_buttons_view, this);

// retrieve views
mFirstButtonView = (TextView) findViewById(R.id.first_button); // is there a chance it will return null?
mSecondButtonView = (TextView) findViewById(R.id.second_button); // is there a chance it will return null?
}
}





My question is: is there any chance that
.findViewById(RESOURCE_ID)
will return
null
right after calling
inflater.inflate(R.layout.two_buttons_view, this);
, or should I call my
init()
method on
onFinishInflate()
callback?

Answer

My question is: is there any chance that .findViewById(RESOURCE_ID) will return null right after calling inflater.inflate(R.layout.two_buttons_view, this)

No, there is not, as long as the views you are looking for are in the layout and you explicitly added to the view's hierarchy. In the end, findViewById loops on View[], filled up by addView.

A small note about

LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.two_buttons_view, this);

ViewGroup has the static method inflate, so you don't need to retrieve the inflater calling getSystemService