将 Butterknife 与 BaseActivity/Child 活动和 MaterialDrawer 一起使用

Posted

技术标签:

【中文标题】将 Butterknife 与 BaseActivity/Child 活动和 MaterialDrawer 一起使用【英文标题】:Using Butterknife with BaseActivity/Child Activities and MaterialDrawer 【发布时间】:2017-08-03 17:22:52 【问题描述】:

我在使用 BaseActivity 实现的多个活动(不使用片段)实现 MaterialDrawer(库 MikePenz)时遇到问题。此外,使用 ButterKnife 绑定视图。

在 SO 中找到相关问题并一一尝试,但在我的情况下它不起作用,因为它们中的大多数使用带有 Fragments 的标准导航抽屉,或者它们与 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_
    android:layout_
    tools:context="com.tvs.ui.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_
        android:layout_
        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_
            android:layout_
            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_
    android:layout_>

    <EditText
        android:id="@+id/searchEditText"
        android:layout_
        android:layout_
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        />

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

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

</android.support.constraint.ConstraintLayout>

我知道错误的原因是 MainActivity 中的 ButterKnife.Bind 在 Layout 膨胀但 Views 在继承的 Activities 中未膨胀时被调用。导航抽屉加载但在单击项目时它失败是显而易见的原因。我不能使用 FrameLayout,因为我使用的 MaterialDrawer 库没有(或者我不知道)有要膨胀的视图。

我尝试了几种广泛搜索 SO 的方法,例如 SO1SO2 Git Git2 Link 但没有成功。

非常感谢任何帮助。提前致谢。

【问题讨论】:

【参考方案1】:

感谢@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,而是使用了 @Nullable 字段。但目前在基础活动和实施活动中都具有约束力。

【讨论】:

activity_main 是在哪里声明的? @LOG_TAG 请检查问题,activity_main 布局以及代码是否存在。 我在上面的代码 BaseActivity 中询问您声明 setContentView(getLayoutResourceId());由于您没有调用 setContentView(R.layout.activity_main); 从您加载 activity_main 的位置;在 BaseActivity(上面的代码)中是否有任何可用的完整要点? 问题已通过在 BaseActivity 中创建抽象方法得到解决,但您在哪里声明 setContentView(R.layout.activity_main); 在基本活动中? @LOG_TAG 是的,通过在 MainActivity 中创建一个抽象方法 protected abstract int getLayoutResourceId();【参考方案2】:

MaterialDrawer 会将视图膨胀到您的布局中。默认情况下,它会将DrawerLayout 添加到您的活动的根目录中,并再次将其他内容(这是您的主布局)添加为子项。

做出这个决定是为了让在您的应用程序中实现Drawer 变得超级简单,而无需更改任何特殊内容。

Butterknife 将在您调用 bind 方法时绑定视图。 MaterialDrawer 的所有视图在您调用 .build() 时都已绑定,但由于 MaterialDrawer 的视图已在内部绑定,因此您不必担心这些。

【讨论】:

感谢您的友好回复。您能否根据我的代码提出建议,如果需要从 BaseActivity 使用我需要做什么? 您并没有真正提到问题所在:D 哦,对不起,迈克。我在 BaseActivity 中使用 MaterialDrawer 并继承了子活动(代码已发布)但抽屉未加载或崩溃 如果我在单个 Activity 中使用 MaterialDrawer,它会加载但是如果我将 MaterialDrawer 代码移动到 BaseActivity 并继承到单个 Activity,它不会加载。我需要与 setContentView 做些什么? 您能否从您的 baseActivity 和扩展此 BaseActivity 的 Activity 中发布代码?我需要看看你是如何启动抽屉的【参考方案3】:

要完成@user2695433 的回答,您可以走得更远一点:处理所有butterknife init 并在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);
  

【讨论】:

以上是关于将 Butterknife 与 BaseActivity/Child 活动和 MaterialDrawer 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

ButterKnife的安装与使用以及ButterKnife右键不显示的大坑

(2016.5.26更新8.0.1失效问题)Android Studio上使用Butterknife注解框架与插件Android Butterknife Zelezny

ButterKnife 注解

Android进阶之光学习记录——注解与依赖注入框架ButterKnife的尝试

Android进阶之光学习记录——注解与依赖注入框架ButterKnife的尝试

Android进阶之光学习记录——注解与依赖注入框架ButterKnife的尝试