Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle butter knife bind in both Baseactivity and sub activities?

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

  1. Call ButterKnife.bind(this) in BaseActivity but not in SplashActivity
  2. Call ButterKnife.bind(this) in both the Activity.
  3. Call 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();

like image 644
GeekDroid Avatar asked Feb 22 '18 05:02

GeekDroid


2 Answers

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

like image 69
Chintan Soni Avatar answered Oct 05 '22 23:10

Chintan Soni


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

like image 29
Mohd Saquib Avatar answered Oct 05 '22 21:10

Mohd Saquib