Использование Butterknife с BaseActivity/Child Activity и MaterialDrawer

У меня возникают проблемы с реализацией MaterialDrawer (библиотека MikePenz) с использованием нескольких действий (без использования фрагментов), которые реализованы с помощью BaseActivity. Кроме того, использование ButterKnife для привязки представлений.

Нашел связанные проблемы здесь, в SO, и попробовал их одну за другой, но в моем случае это не сработало, поскольку большинство из них используют стандартный навигационный ящик с фрагментами или они не связаны с ButterKnife.

Код :

Класс MainActivity

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

<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>

МагазинАктивность

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

<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>

Я понимаю, что причина ошибки в том, что ButterKnife.Bind в MainActivity вызывается, когда макет раздут, но представления не раздуты в унаследованных действиях. Ящик навигации загружается, но при нажатии на элемент он не работает по очевидной причине. Я не могу использовать FrameLayout, так как я использую библиотеку MaterialDrawer, которая не имеет (или я не знаю) представлений для раздувания.

Я испробовал несколько методов обширного поиска SO, например SO1SO2 Git Git2 Ссылка, но не было успешным.

Благодарим за любую помощь. Заранее спасибо.


person user2695433    schedule 03.08.2017    source источник


Ответы (3)


Спасибо @mikepenz за ответ.

Выкладываю, может кому поможет

Проблема была устранена путем создания абстрактного метода в BaseActivity.

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

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

    }
    protected abstract int getLayoutResourceId();

Конкретная деятельность

@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;
}

Обратите внимание, что я не использовал ButterKnife.Bind в Concrete Activity и использовал поля @Nullable. Но в настоящее время Binding как в базовой, так и в реализующей деятельности.

person user2695433    schedule 04.08.2017
comment
где объявлена ​​активность_main? - person LOG_TAG; 04.03.2018
comment
@LOG_TAG, пожалуйста, проверьте вопрос, макет Activity_main, а также код есть. - person user2695433; 06.03.2018
comment
Я спрашиваю в приведенном выше коде BaseActivity, где вы объявили setContentView(getLayoutResourceId()); откуда вы загружаете activity_main, так как вы не вызывали setContentView(R.layout.activity_main); в BaseActivity (выше кода) доступен какой-либо полностью рабочий смысл? - person LOG_TAG; 07.03.2018
comment
Проблема была устранена путем создания абстрактного метода в BaseActivity, но где вы объявляли setContentView(R.layout.activity_main); в базовой активности? - person LOG_TAG; 07.03.2018
comment
@LOG_TAG да, создав абстрактный метод в MainActivity protected abstract int getLayoutResourceId(); - person user2695433; 08.03.2018
comment
@LOG_TAG это есть в ответе, опубликованном самостоятельно - person user2695433; 08.03.2018
comment
Спасибо за ваш ответ! Вы имеете в виду, что содержимое activity_main должно быть перемещено в activity_stores с помощью этого ‹include layout =activity_main, чтобы мы получали представление навигации по каждому конкретному действию? у вас есть образец в github? - person LOG_TAG; 08.03.2018

MaterialDrawer увеличит количество просмотров до вашего макета. По умолчанию он добавит DrawerLayout в корень вашей активности и снова добавит к нему другой контент (который является вашим основным макетом) как дочерний.

Это решение было принято для того, чтобы максимально упростить внедрение Drawer в ваше приложение без необходимости каких-либо особых изменений.

Butterknife свяжет представления во время вызова метода bind. Все представления MaterialDrawer связаны во время вызова .build(), но, поскольку представления MaterialDrawer связаны внутри, вам не нужно беспокоиться об этом.

person mikepenz    schedule 04.08.2017
comment
Спасибо за ваш добрый ответ. Не могли бы вы предложить в соответствии с моим кодом, что мне нужно сделать, если нужно использовать из BaseActivity? - person user2695433; 04.08.2017
comment
Вы не упомянули, в чем проблема :D - person mikepenz; 04.08.2017
comment
О, прости, Майк. Я использую MaterialDrawer в BaseActivity, и у меня есть дочерние действия, унаследованные от этого (код опубликован). Но Drawer не загружается или аварийно завершает работу. - person user2695433; 04.08.2017
comment
Если я использую MaterialDrawer в отдельном действии, оно загружается. Но если я перемещаю код MaterialDrawer в BaseActivity и наследую отдельные действия, оно не загружается. Что-то, что мне нужно сделать с setContentView? - person user2695433; 04.08.2017
comment
Не могли бы вы опубликовать код из вашей базовой активности и активности, которая расширяет эту базовую активность? Мне нужно увидеть, как вы открываете ящик - person mikepenz; 04.08.2017
comment
Майк, теперь я могу загрузить Drawer, сделав базовую активность абстрактной и переопределив setcontentview. Но, имея это, есть ли способ получить ящик из расширенной активности, чтобы выбрать его? - person user2695433; 04.08.2017
comment
Что ж, я до сих пор не вижу вашего кода, но я бы сказал, что вы просто сохраняете объект Drawer в своем AbstractActivity и делаете его закрытым пакетом или около того, а затем вы можете получить доступ к этому объекту в вашем расширении Activity и выбрать позицию или что-то еще нужно - person mikepenz; 04.08.2017
comment
Давайте продолжим обсуждение в чате. - person user2695433; 04.08.2017

Чтобы завершить ответ @ user2695433, вы можете пойти немного дальше: обработать все инициализации Butterknife и закрыть в BaseActivity, чтобы вы не могли забыть освободить ресурсы! Очень полезно, если в вашу команду приходит какой-то новый разработчик и не знает, как работает мастихин. Вот :

--------В 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
}

----- В 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);
  }
person Dagnogo Jean-François    schedule 24.12.2017