Кнопка NPE с использованием Butterknife

Я пытаюсь выполнить упражнение с edx.org (Chat Firebase, весь код с https://github.com/ykro/android-chat-firebase) и не могу понять, откуда появляется эта ошибка, это NPE, но это меня сбивает, он падает, когда приложение работает на Genymotion Emulator.

ОШИБКА

java.lang.RuntimeException: Unable to start activity ComponentInfo{cat.edx_manel.exercises.chatfirebase/cat.edx_manel.exercises.chatfirebase.activities.LoginActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setEnabled(boolean)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)                                                                                     
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setEnabled(boolean)' on a null object reference
at cat.edx_manel.exercises.chatfirebase.activities.LoginActivity.setInputs(LoginActivity.java:114)
at cat.edx_manel.exercises.chatfirebase.activities.LoginActivity.disableInputs(LoginActivity.java:57)
at cat.edx_manel.exercises.chatfirebase.implementations.login.LoginPresenterImpl.checkForAuthenticateUser(LoginPresenterImpl.java:43)
at cat.edx_manel.exercises.chatfirebase.activities.LoginActivity.onCreate(LoginActivity.java:46)
at android.app.Activity.performCreate(Activity.java:6237)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:110)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
at android.app.ActivityThread.-wrap11(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:5417) 
at java.lang.reflect.Method.invoke(Native Method)

LOGINACTIVITY

public class LoginActivity extends AppCompatActivity implements LoginView {

@BindView(R.id.user)
EditText inputEmail;
@BindView(R.id.pass)
EditText inputPassword;
@BindView(R.id.signIn)
Button btnSignIn;
@BindView(R.id.signUp)
Button btnSignUp;
@BindView(R.id.progressBar)
ProgressBar progressBar;
@BindView(R.id.layoutMainContainer)
RelativeLayout container;

private LoginPresenter loginPresenter;

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

    loginPresenter = new LoginPresenterImpl(this);
    loginPresenter.onCreate();
    loginPresenter.checkForAuthenticateUser();
}

@Override
protected void onDestroy() {
    loginPresenter.onDestroy();
    super.onDestroy();
}

@Override
public void disableInputs() {
    setInputs(false);
}

@Override
public void enableInputs() {
    setInputs(true);
    hideProgress();
}

@Override
public void showProgress() {
    progressBar.setVisibility(View.VISIBLE);
}

@Override
public void hideProgress() {
    progressBar.setVisibility(View.INVISIBLE);
}

@Override
@OnClick(R.id.signUp)
public void handleSignUp() {
    loginPresenter.registerNewUser(inputEmail.getText().toString(),
            inputPassword.getText().toString());
}
@Override
@OnClick(R.id.signIn)
public void handleSignIn() {
    loginPresenter.validateLogin(inputEmail.getText().toString(),
            inputPassword.getText().toString());
}

@Override
public void navigateToMainScreen() {
    startActivity(new Intent(this, ContactListActivity.class));
}

@Override
public void loginError(String error) {
    inputPassword.setText("");
    String msgError = String.format(getString(R.string.login_error_message_signin), error);
    inputPassword.setError(msgError);
}

@Override
public void newUserSuccess() {
    Snackbar.make(container, R.string.login_error_message_signup, Snackbar.LENGTH_SHORT).show();
}

@Override
public void newUserError(String error) {
    inputPassword.setText("");
    String msgError = String.format(getString(R.string.login_error_message_signup), error);
    inputPassword.setError(msgError);
}

private void setInputs(boolean enabled) {
    btnSignIn.setEnabled(enabled);
    btnSignUp.setEnabled(enabled);
    inputEmail.setEnabled(enabled);
    inputPassword.setEnabled(enabled);
    }
}

Как вы видите, кнопка связана с фреймворком Butterknife, но я не знаю, с чем это связано...

Большое вам спасибо

ОБНОВЛЕНО

ПЛАНИРОВКА

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layoutMainContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".activities.LoginActivity">

<android.support.design.widget.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textPersonName"
        android:hint="Name"
        android:ems="10"
        android:id="@+id/user"/>

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

<android.support.design.widget.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textPersonName"
        android:hint="Password"
        android:ems="10"
        android:id="@+id/pass"/>

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

<LinearLayout
    android:id="@+id/layoutButtons"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <Button
        android:id="@+id/signIn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/signUp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

<ProgressBar
    style="?android:attr/progressBarStyleLarge"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/progressBar"
    android:layout_below="@id/layoutButtons"/>

ОБНОВЛЕНИЕ 2

LOGINVIEW ИНТЕРФЕЙС

public interface LoginView {
void enableInputs();
void disableInputs();
void showProgress();
void hideProgress();

void handleSignUp();
void handleSignIn();

void navigateToMainScreen();
void loginError(String error);

void newUserSuccess();
void newUserError(String error);
}

2 ответа

Во-первых, вот один из моих ответов, которым я поделился, чтобы правильно настроить ButterKnife.

Рассмотрим эту возможную проблему:

Что вы здесь переопределяете?

@Override //this line here
@OnClick(R.id.signUp)
public void handleSignUp() {
   loginPresenter.registerNewUser(inputEmail.getText().toString(),
        inputPassword.getText().toString());
}

@Override //this line here
@OnClick(R.id.signIn)
public void handleSignIn() {
   loginPresenter.validateLogin(inputEmail.getText().toString(),
        inputPassword.getText().toString());
}

Попробуйте это без переопределений:

@OnClick(R.id.signUp)
public void handleSignUp() {
   loginPresenter.registerNewUser(inputEmail.getText().toString(),
        inputPassword.getText().toString());
}


@OnClick(R.id.signIn)
public void handleSignIn() {
  loginPresenter.validateLogin(inputEmail.getText().toString(),
        inputPassword.getText().toString());
}

Затем очистите ваш проект и запустите снова!

Надеюсь, это поможет!

Я имею в виду учебник на уроке ButterKnife. Я думаю, что вместо @BindView это должно быть @Bind

@Bind(R.id.button)
Button button;
@Bind(R.id.textView)
TextView textView;
@Bind(R.id.radioButton)
RadioButton radioButton;
@Bind(R.id.checkBox)
Другие вопросы по тегам