0

I'm facing issues implementing MaterialDrawer (library MikePenz) using Multiple Activities ( not using fragments) which is implemented with a BaseActivity. Also, using ButterKnife to bind the views.

Found related issues here in SO and tried it out one by one , but in my case it was not working since most of them using standard Navigation Drawer with Fragments or they are not related with ButterKnife.

Code :

MainActivity class

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.toolbar)
    Toolbar toolbar;

    private List<TestModel> destinations;
    private DestinationAdapter mAdapter;
    ProgressDialog progressDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        setSupportActionBar(toolbar);
        navManagement();
    }
}

activity_main layout

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/maincontainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.tvs.ui.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        >

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay"
             />

    </android.support.design.widget.AppBarLayout>

</android.support.constraint.ConstraintLayout>

StoreActivity

public class StoresActivity extends MainActivity {

    @BindView(R.id.searchEditText)
    EditText mSearchEditText; // errorRequired view 'searchEditText' with ID 2131558557 for field 'mSearchEditText' was not found
    @BindView(R.id.storesRecyclerView)
    RecyclerView recyclerView; // here too

    private List<TestModel> stores;
    private StoreAdapter mAdapter;

    //endregion
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_stores);
        ButterKnife.bind(this);

        loadRecyclerView();
        testData();

    }
    }

activity_store layout

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/searchEditText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/storesRecyclerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:scrollbars="vertical">

    </android.support.v7.widget.RecyclerView>

</android.support.constraint.ConstraintLayout>

I understand that cause of error is that the ButterKnife.Bind in MainActivity is called when the Layout is inflated but the Views are not inflated in the inherited Activities . The Navigation drawer loads but on clicking item it fails as obvious reason. I cannot use a FrameLayout since I'm using MaterialDrawer library which doesn't ( or I'm not aware) have views to inflate.

I tried several methods extensively searching SO like SO1SO2 Git Git2 Link but was not successful .

Appreciate any help are deeply appreciated . Thanks in advance.

user2695433
  • 2,013
  • 4
  • 25
  • 44

3 Answers3

2

Thanks @mikepenz for the response.

Posting it since it might help somebody

The issue was fixed by creating an abstract method in BaseActivity

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutResourceId());

        ButterKnife.bind(this); 
        setSupportActionBar(toolbar);
        navManagement();

    }
    protected abstract int getLayoutResourceId();

Concrete Activity

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //setContentView(R.layout.activity_stores); not required
    ButterKnife.bind(this); 

    loadRecyclerView();
    testData();

}

@Override
protected int getLayoutResourceId() {
    return R.layout.activity_stores;
}

Please note that I was not using ButterKnife.Bind in the Concrete Activity and used @Nullable fields. But currently Binding in both Base and Implementing Activities.

user2695433
  • 2,013
  • 4
  • 25
  • 44
  • where activity_main is declared? – LOG_TAG Mar 03 '18 at 22:33
  • @LOG_TAG please check the question, activity_main layout as well as code is there. – user2695433 Mar 06 '18 at 05:16
  • I'm asking in above code BaseActivity where you declared setContentView(getLayoutResourceId()); from where you are loading activity_main since you didn't called setContentView(R.layout.activity_main); in BaseActivity (above code) any fully working gist available? – LOG_TAG Mar 07 '18 at 10:24
  • The issue was fixed by creating an abstract method in BaseActivity, but where you declaring *setContentView(R.layout.activity_main);* in base activity? – LOG_TAG Mar 07 '18 at 10:38
  • @LOG_TAG yes, by creating an abstract method in MainActivity protected abstract int getLayoutResourceId(); – user2695433 Mar 08 '18 at 06:48
  • @LOG_TAG its there in the answer posted itsef – user2695433 Mar 08 '18 at 06:52
  • Thanks for your all response! you mean activity_main contents should be moved to *activity_stores* by using this * – LOG_TAG Mar 08 '18 at 09:05
1

The MaterialDrawer will inflate views to your layout. By default it will add a DrawerLayout into the root of your activity, and add the other content (which is your main layout) as child to it again.

This decision was made to make it super simple to implement a Drawer into your application without needing to alter anything special.

Butterknife will bind the view's at the time you call the bind method. All views of the MaterialDrawer, are bound at the time of you calling .build(), but as the views of the MaterialDrawer are bound internally you shouldn't have to worry about these.

mikepenz
  • 12,708
  • 14
  • 77
  • 117
  • Thanks for your kind response. Can you please suggest as per my code , what I need to do if needed to be used from a BaseActivity? – user2695433 Aug 04 '17 at 09:36
  • You did not really mention what's the issue :D – mikepenz Aug 04 '17 at 09:57
  • Oh Sorry Mike. I'm using MaterialDrawer in BaseActivity and have Child Activities inherited from this (Code posted ) But the Drawer is not loaded or crashes – user2695433 Aug 04 '17 at 10:12
  • If I use MaterialDrawer in individual Activity it loads But if I'm moving the MaterialDrawer code to a BaseActivity and inherit to individual Activities its not loading. Something I need to do with setContentView ? – user2695433 Aug 04 '17 at 10:22
  • Can you please post the code From your baseActivity and an Activity which extends this BaseActivity? I'd need to see how you init the drawer – mikepenz Aug 04 '17 at 10:58
  • Mike , now I'm able to load the Drawer by making the Base Activity an abstract one and overriding the setcontentview. But having this, is there any way that I can get the Drawer from the extended activity inorder to select it selected? – user2695433 Aug 04 '17 at 11:00
  • Well I still do not see your code, but I would say you just keep the `Drawer` object in your `AbstractActivity` and make it package private or so, and then you can access this object in your extending `Activity` and select the position, or whatever needed – mikepenz Aug 04 '17 at 11:56
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/151056/discussion-between-user2695433-and-mikepenz). – user2695433 Aug 04 '17 at 12:05
0

To complete @user2695433 's answer, you can go a little futher : handle all butterknife init and close in the BaseActivity so you can't forget to release ressources ! Very useful if some new dev come in your team and dont know how butterknife work. Here it is :

--------In BaseActivity-------

protected Unbinder binder;
protected abstract int getLayoutResourceId();
...

  @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutResourceId());
        binder = ButterKnife.bind(this);
    }

@Override
protected void onDestroy() {
    super.onDestroy();
    binder.unbind(); //release ressource
}

----- In ConcreteActivity------------

@BindView(R.id.title)
    TextView title; // butterknife stuff

@Override
    protected int getLayoutResourceId() { //define which Id
        return R.layout.activity_main;
    }
 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
  }