如何调试Butterknife在Android应用程序中引发的Null指针异常?

时间:2016-05-03 12:52:09

标签: java android nullpointerexception

我还有另一个新手问题。正如您在我的错误消息中看到的那样。在我的MainActivity.java中,第125行显示空指针异常:

    05-03 22:19:17.559 22615-22615/com.example.andrewjakevillegas.stormy E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.andrewjakevillegas.stormy, PID: 22615
java.lang.
NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
at com.example.andrewjakevillegas.stormy.MainActivity.updateDisplay(MainActivity.java:125)
at com.example.andrewjakevillegas.stormy.MainActivity.access$200(MainActivity.java:38)
at com.example.andrewjakevillegas.stormy.MainActivity$1$1.run(MainActivity.java:100)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
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)

这是我的MainActivity.java

package com.example.andrewjakevillegas.stormy;

import...    

public class MainActivity extends ActionBarActivity {

    public static final String TAG = MainActivity.class.getSimpleName();

    private CurrentWeather mCurrentWeather;

    @BindView(R.id.timeLabel)
    TextView mTimeLabel;
    @BindView(R.id.temperatureLabel)
    TextView mTemperatureLabel;
    @BindView(R.id.humidityLabel)
    TextView mHumidityValue;
    @BindView(R.id.precipLabel)
    TextView mPrecipValue;
    @BindView(R.id.summaryLabel)
    TextView mSummaryLabel;
    @BindView(R.id.iconImageView)
    ImageView mIconImageView;
    /**
     * ATTENTION: This was auto-generated to implement the App Indexing API.
     * See https://g.co/AppIndexing/AndroidStudio for more information.
     */
    private GoogleApiClient mClient;


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



        if (isNetworkAvailable()) {
            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder()
                    .url( forecastURL )
                    .build();

            Call call = client.newCall( request );
            call.enqueue( new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {

                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {

                    try {
                        String jsonData = response.body().string();
                        Log.v( TAG, jsonData );
                        if (response.isSuccessful()) {
                            mCurrentWeather = getCurrentDetails( jsonData );
                            runOnUiThread( new Runnable() {
                                @Override
                                public void run() {
                                    updateDisplay();
                                }
                            } );
                        } else {
                            alertUserAboutError();
                        }
                    } catch (IOException e) {
                        Log.e( TAG, "Exception caught: ", e );
                    } catch (JSONException e) {
                        Log.e( TAG, "Exception caught: ", e );
                    }
                }
            } );
        } else {
            Toast.makeText( this, getString( R.string.network_unavailable_message ),
                    Toast.LENGTH_LONG ).show();
        }
        Log.d( TAG, "Main UI code is running!" );

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        mClient = new GoogleApiClient.Builder( this ).addApi( AppIndex.API ).build();
    }

    private void updateDisplay() {
        mTemperatureLabel.setText( mCurrentWeather.getTemperature() + "" );
    }

    private CurrentWeather getCurrentDetails(String jsonData) throws JSONException {
        JSONObject forecast = new JSONObject( jsonData );
        String timezone = forecast.getString( "timezone" );
        Log.i( TAG, "From JSON: " + timezone );

        JSONObject currently = forecast.getJSONObject( "currently" );
        CurrentWeather currentWeather = new CurrentWeather();
        currentWeather.setHumidity( currently.getDouble( "humidity" ) );
        currentWeather.setTime( currently.getLong( "time" ) );
        currentWeather.setIcon( currently.getString( "icon" ) );
        currentWeather.setPrecipChance( currently.getDouble( "precipProbability" ) );
        currentWeather.setSummary( currently.getString( "summary" ) );
        currentWeather.setTemperature( currently.getDouble( "temperature" ) );

        return new CurrentWeather();
    }

    private boolean isNetworkAvailable() {
        ConnectivityManager manager = (ConnectivityManager)
                getSystemService( Context.CONNECTIVITY_SERVICE );
        NetworkInfo networkInfo = manager.getActiveNetworkInfo();
        boolean isAvailable = false;
        if (networkInfo != null && networkInfo.isConnected()) {
            isAvailable = true;
        }

        return isAvailable;
    }

    private void alertUserAboutError() {
        AlertDialogFragment dialog = new AlertDialogFragment();
        dialog.show( getFragmentManager(), "error_dialog" );
    }

    @Override
    public void onStart() {
        super.onStart();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        mClient.connect();
        Action viewAction = Action.newAction(
                Action.TYPE_VIEW, // TODO: choose an action type.
                "Main Page", // TODO: Define a title for the content shown.
                // TODO: If you have web page content that matches this app activity's content,
                // make sure this auto-generated web page URL is correct.
                // Otherwise, set the URL to null.
                Uri.parse( "http://host/path" ),
                // TODO: Make sure this auto-generated app URL is correct.
                Uri.parse( "android-app://com.example.andrewjakevillegas.stormy/http/host/path" )
        );
        AppIndex.AppIndexApi.start( mClient, viewAction );
    }

    @Override
    public void onStop() {
        super.onStop();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        Action viewAction = Action.newAction(
                Action.TYPE_VIEW, // TODO: choose an action type.
                "Main Page", // TODO: Define a title for the content shown.
                // TODO: If you have web page content that matches this app activity's content,
                // make sure this auto-generated web page URL is correct.
                // Otherwise, set the URL to null.
                Uri.parse( "http://host/path" ),
                // TODO: Make sure this auto-generated app URL is correct.
                Uri.parse( "android-app://com.example.andrewjakevillegas.stormy/http/host/path" )
        );
        AppIndex.AppIndexApi.end( mClient, viewAction );
        mClient.disconnect();
    }
}

这段特殊代码令我头痛。这是我的错误日志中的第125行。

private void updateDisplay() {
        mTemperatureLabel.setText( mCurrentWeather.getTemperature() + "" );
    }

我检查了我的布局。我得到了正确的文本视图ID和类型。

这是我的activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingLeft="@dimen/activity_horizontal_margin"
            android:paddingRight="@dimen/activity_horizontal_margin"
            android:paddingTop="@dimen/activity_vertical_margin"
            android:paddingBottom="@dimen/activity_vertical_margin"
            tools:context=".MainActivity"
            android:id="@+id/relativeLayout"
            android:background="#fffc970b">

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/temperatureLabel"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true"
    android:textColor="@android:color/white"
    android:textSize="150dp"
    android:text="100"/>

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/degreeImageView"
    android:layout_alignTop="@+id/temperatureLabel"
    android:layout_toRightOf="@+id/temperatureLabel"
    android:layout_toEndOf="@+id/temperatureLabel"
    android:layout_marginTop="50dp"
    android:src="@drawable/degree"/>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="At 5:00 PM it will be"
    android:id="@+id/timeLabel"
    android:layout_above="@+id/temperatureLabel"
    android:layout_centerHorizontal="true"
    android:textColor="#95ffffff"
    android:textSize="18sp"/>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Alcatraz Island, CA"
    android:id="@+id/locationLabel"
    android:layout_above="@+id/timeLabel"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="60dp"
    android:textColor="@android:color/white"
    android:textSize="24sp"/>

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/iconImageView"
    android:layout_alignBottom="@+id/locationLabel"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:src="@drawable/cloudy_night"/>

<LinearLayout
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/temperatureLabel"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="10dp"
    android:weightSum="100"
    android:id="@+id/linearLayout">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="50">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="HUMIDITY"
            android:id="@+id/humidityLabel"
            android:textColor="#95ffffff"
            android:gravity="center_horizontal"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="0.88"
            android:id="@+id/humidityValue"
            android:textColor="@android:color/white"
            android:textSize="24sp"
            android:gravity="center_horizontal"/>
    </LinearLayout>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="50">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="RAIN/SNOW?"
            android:id="@+id/precipLabel"
            android:textColor="#95ffffff"
            android:gravity="center_horizontal"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="100"
            android:id="@+id/precipValue"
            android:textColor="@android:color/white"
            android:textSize="24sp"
            android:gravity="center_horizontal"/>
    </LinearLayout>
</LinearLayout>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Stormy with a chance of meatballs"
    android:id="@+id/summaryLabel"
    android:layout_below="@+id/linearLayout"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="40dp"
    android:textColor="@android:color/white"
    android:textSize="18dp"
    android:gravity="center_horizontal"/>

My Current Weather Java Class应该获取并设置正确的值。

public int getTemperature() {
    return (int)Math.round(mTemperature);
}

public void setTemperature(double temperature) {
    mTemperature = temperature;
}

以下是我的CurrentWeather.java的副本,以防你需要引用它。

    package com.example.andrewjakevillegas.stormy;

public class CurrentWeather {
    private String mIcon;
    private long mTime;
    private double mTemperature;
    private double mHumidity;
    private double mPrecipChance;
    private String mSummary;

    public String getIcon() {
        return mIcon;
    }

    public void setIcon(String icon) {
        mIcon = icon;
    }

    public int getIconId(){
        int iconId = R.drawable.clear_day;

        if (mIcon.equals("clear-day")){
            iconId = R.drawable.clear_day;
        }

        else if (mIcon.equals("clear-night")){
            iconId = R.drawable.clear_night;
        }

        else if (mIcon.equals("rain")) {
            iconId = R.drawable.rain;
        }
        else if (mIcon.equals("snow")) {
            iconId = R.drawable.snow;
        }
        else if (mIcon.equals("sleet")) {
            iconId = R.drawable.sleet;
        }
        else if (mIcon.equals("wind")) {
            iconId = R.drawable.wind;
        }
        else if (mIcon.equals("fog")) {
            iconId = R.drawable.fog;
        }
        else if (mIcon.equals("cloudy")) {
            iconId = R.drawable.cloudy;
        }
        else if (mIcon.equals("partly-cloudy-day")) {
            iconId = R.drawable.partly_cloudy;
        }
        else if (mIcon.equals("partly-cloudy-night")) {
            iconId = R.drawable.cloudy_night;
        }


        return iconId;
    }

    public long getTime() {
        return mTime;
    }

    public void setTime(long time) {
        mTime = time;
    }

    public int getTemperature() {
        return (int)Math.round(mTemperature);
    }

    public void setTemperature(double temperature) {
        mTemperature = temperature;
    }

    public double getHumidity() {
        return mHumidity;
    }

    public void setHumidity(double humidity) {
        mHumidity = humidity;
    }

    public double getPrecipChance() {
        double precipPercentage = mPrecipChance * 100;
        return (int)Math.round(precipPercentage);
    }

    public void setPrecipChance(double precipChance) {
        mPrecipChance = precipChance;
    }

    public String getSummary() {
        return mSummary;
    }

    public void setSummary(String summary) {
        mSummary = summary;
    }


}

以下是运行调试器时的图像结果。

enter image description here

奶油刀的样子不起作用。您有什么建议我可以解决这个问题吗?

4 个答案:

答案 0 :(得分:3)

我找到了问题的答案。

您必须下载 - 将整个butterknife编译器(下面的代码)复制并粘贴到您的构建gradle中。我只是复制依赖项并将其添加到我的gradle依赖项中。这给了我这个问题。

buildscript {
  repositories {
    mavenCentral()
   }
  dependencies {
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
  }
}

apply plugin: 'com.neenbedankt.android-apt'

dependencies {
  compile 'com.jakewharton:butterknife:8.0.1'
  apt 'com.jakewharton:butterknife-compiler:8.0.1'
}

答案 1 :(得分:0)

为什么在单独的runnable中使用updateDisplay?然后在主线程上运行这个新的runnable。看起来很奇怪。

无论如何,问题是你的mTemperatureLabel没有被初始化。调用第一个updateDisplay方法时,可能没有完成bindView操作。

编辑:正如我在评论中提到的,我不会使用Butterknife,因为没有任何好处,你会在调试错误时遇到问题。无论如何,如果你想使用Butterknife无论如何,试试Bind而不是BindView。

答案 2 :(得分:0)

package com.example.com;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;


import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.common.api.GoogleApiClient;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;

 import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;

import butterknife.Bind;
import butterknife.ButterKnife;

public class MainActivity extends AppCompatActivity {

public static final String TAG = MainActivity.class.getSimpleName();

private CurrentWeather mCurrentWeather;

@Bind(R.id.timeLabel)
TextView mTimeLabel;
@Bind(R.id.temperatureLabel)
TextView mTemperatureLabel;
@Bind(R.id.humidityLabel)
TextView mHumidityValue;
@Bind(R.id.precipLabel)
TextView mPrecipValue;
@Bind(R.id.summaryLabel)
TextView mSummaryLabel;
[![enter image description here][1]][1]@Bind(R.id.iconImageView)
ImageView mIconImageView;
/**
 * ATTENTION: This was auto-generated to implement the App Indexing API.
 * See https://g.co/AppIndexing/AndroidStudio for more information.
 */
private GoogleApiClient mClient;


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


    String apiKey = "ur_key";
    double latitude = 37.8267;
    double longitude = -122.423;
    String forecastURL = "https://api.forecast.io/forecast/" + apiKey +
            "/" + latitude + "," + longitude;

    if (isNetworkAvailable()) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url( forecastURL )
                .build();

        Call call = client.newCall( request );
        call.enqueue( new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {

            }

            @Override
            public void onResponse(Response response) throws IOException {

                try {
                    String jsonData = response.body().string();
                    Log.v( TAG, jsonData );
                    if (response.isSuccessful()) {
                        mCurrentWeather = getCurrentDetails( jsonData );
                        runOnUiThread( new Runnable() {
                            @Override
                            public void run() {
                                updateDisplay();
                            }
                        } );
                    } else {
                        alertUserAboutError();
                    }
                } catch (IOException e) {
                    Log.e( TAG, "Exception caught: ", e );
                } catch (JSONException e) {
                    Log.e( TAG, "Exception caught: ", e );
                }
            }
        } );
    } else {
        Toast.makeText( this,  "not available",Toast.LENGTH_SHORT )
               .show();
    }
    Log.d( TAG, "Main UI code is running!" );

    // ATTENTION: This was auto-generated to implement the App Indexing API.
    // See https://g.co/AppIndexing/AndroidStudio for more information.
    mClient = new GoogleApiClient.Builder( this ).addApi( AppIndex.API ).build();
            }


private void updateDisplay() {
    mTemperatureLabel.setText( mCurrentWeather.getTemperature() + "" );
}

private CurrentWeather getCurrentDetails(String jsonData) throws JSONException {
    JSONObject forecast = new JSONObject( jsonData );
    String timezone = forecast.getString( "timezone" );
    Log.i( TAG, "From JSON: " + timezone );

    JSONObject currently = forecast.getJSONObject( "currently" );
    CurrentWeather currentWeather = new CurrentWeather();
    currentWeather.setHumidity( currently.getDouble( "humidity" ) );
    currentWeather.setTime( currently.getLong( "time" ) );
    currentWeather.setIcon( currently.getString( "icon" ) );
    currentWeather.setPrecipChance( currently.getDouble( "precipProbability" ) );
    currentWeather.setSummary( currently.getString( "summary" ) );
    currentWeather.setTemperature( currently.getDouble( "temperature" ) );

    return new CurrentWeather();
}

private boolean isNetworkAvailable() {
    ConnectivityManager manager = (ConnectivityManager)
            getSystemService( Context.CONNECTIVITY_SERVICE );
    NetworkInfo networkInfo = manager.getActiveNetworkInfo();
    boolean isAvailable = false;
    if (networkInfo != null && networkInfo.isConnected()) {
        isAvailable = true;
    }

    return isAvailable;
}

private void alertUserAboutError() {
    AlertDialogFragment dialog = new AlertDialogFragment();
    dialog.show( getFragmentManager(), "error_dialog" );
}

@Override
public void onStart() {
    super.onStart();

    // ATTENTION: This was auto-generated to implement the App Indexing API.
    // See https://g.co/AppIndexing/AndroidStudio for more information.
    mClient.connect();
    Action viewAction = Action.newAction(
            Action.TYPE_VIEW, // TODO: choose an action type.
            "Main Page", // TODO: Define a title for the content shown.
            // TODO: If you have web page content that matches this app activity's content,
            // make sure this auto-generated web page URL is correct.
            // Otherwise, set the URL to null.
            Uri.parse( "http://host/path" ),
            // TODO: Make sure this auto-generated app URL is correct.
            Uri.parse( "android-app://com.example.com/http/host/path" )
    );
    AppIndex.AppIndexApi.start( mClient, viewAction );
}

@Override
public void onStop() {
    super.onStop();

    // ATTENTION: This was auto-generated to implement the App Indexing API.
    // See https://g.co/AppIndexing/AndroidStudio for more information.
    Action viewAction = Action.newAction(
            Action.TYPE_VIEW, // TODO: choose an action type.
            "Main Page", // TODO: Define a title for the content shown.
            // TODO: If you have web page content that matches this app activity's content,
            // make sure this auto-generated web page URL is correct.
            // Otherwise, set the URL to null.
            Uri.parse( "http://host/path" ),
            // TODO: Make sure this auto-generated app URL is correct.
            Uri.parse( "android-app://com.example.andrewjakevillegas.stormy/http/host/path" )
    );
    AppIndex.AppIndexApi.end( mClient, viewAction );
    mClient.disconnect();
}

enter image description here

答案 3 :(得分:0)

在我的情况下,我有不同的依赖

首先,你的文件build.grade

中有类似的配置

问题差异版本[8.0.1!= 8.2.1]

的build.gradle(应用的)

dependencies {
         compile 'com.jakewharton:butterknife:8.2.1'
         apt 'com.jakewharton:butterknife-compiler:8.0.1'
}

我使用类似版本解决了

dependencies {
         compile 'com.jakewharton:butterknife:8.2.1'
         apt 'com.jakewharton:butterknife-compiler:8.2.1'
}

的build.gradle

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.0'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'

    }
}

祝你好运!