There is a BaseActivity with a layout and a sub Activity that extends this BaseActivity.
How do you bind views so that views in BaseActivity are binded in BaseActivity and views in Sub activity are binded there ?
Here is a sample code explaining the current scenario, Note: Sample code was taken from here
BASE ACTIVITY
public class BaseActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState, int layout) {
super.onCreate(savedInstanceState);
super.setContentView(layout);
ButterKnife.bind(this);
}
@Override
public void setContentView(int layoutResID) {
//I added my own implementation here
}
}
SUB ACTIVITY
public class SplashActivity extends BaseActivity {
@BindView(R.id.txtName)
TextView txtName;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ButterKnife.bind(this);
}
}
The above scenario produced many errors such as unable to find view with the id,
After tons of researching I found a lot of topics discussing the same,
Link 1
Link 2
Link 3
Link 4
So after going through all the links I tried the following combinations but none of them worked
ButterKnife.bind(this)
in BaseActivity but not in SplashActivity
ButterKnife.bind(this)
in both the Activity.ButterKnife.bind(this)
in SplashActivity
, with this combination I was unable to access the BaseActivity's view items as they turned out to be null.My Question
How do you bind both the BaseActivity
and SplashActivity
View items ?
Exact Error line
Caused by: java.lang.IllegalStateException: Required view '' with ID 2131296567 for field '' was not found. If this view is optional add '@Nullable' (fields) or '@Optional' (methods) annotation.
For your kind note, the Views exist in the layout.
Edit 1:
I have added code that overrides the setContentView();
Its simple.
Have your abstract BaseActivity as:
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutResource());
ButterKnife.bind(this);
}
protected abstract int getLayoutResource();
}
Then simply extend your activity with BaseActivity
as:
public class SplashActivity extends BaseActivity {
@BindView(R.id. txtName)
TextView textView;
@Override
protected int getLayoutResource() {
return R.layout.activity_splash;
}
}
I prefer to have multiple Base classes in my project. You can have a BaseToolbarActivity
that will extend BaseActivity
as:
public abstract class BaseToolBarActivity extends BaseActivity {
protected static final int RESOURCE_NO_MENU = 0;
@BindView(R.id.toolbar)
Toolbar mToolbar;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setToolBar();
}
public void setToolBar() {
setSupportActionBar(mToolbar);
}
protected abstract int getMenuResource();
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (getMenuResource() == RESOURCE_NO_MENU)
return super.onCreateOptionsMenu(menu);
else {
getMenuInflater().inflate(getMenuResource(), menu);
return true;
}
}
}
So, if your Activity
has layout Toolbar, then extend it to BaseToolbarActivity
, else extend it to BaseActivity
For more such classes, you can refer my project at
https://github.com/chintansoni202/Android-Master-Project
The message in the exception tells you what to do:
Required view 'txtName' with ID 2131296567 for field 'txtName' was not found. If this view is optional add '@nullable' annotation.
Either add it to your layout or make the field binding optional with a @Nullable annotation.
See this Link
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With