Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Android Build a Weather App (2015) Hooking Up the Model to the View Plugging in the Data

Mark Junge
Mark Junge
1,374 Points

NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on

My code looks like this (as in the video)

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();
                            }
                        });

private void updateDisplay() {

  (xx)  mTemperatureLabel.setText(mCurrentWeather.getTemperature() + "");
  // mTimeLabel.setText(" At " + mCurrentWeather.getFormatedTime() + " it will be ");
}

I wonder why i cant run, it constantly stop the stormy app. It is line (xx) that is the problem, if i note it out, the app run with my hard coded numbers and text.

Have used 2 hours on this problem now, please help me someone :-)

Mark Junge
Mark Junge
1,374 Points

I have missed this on Butterknife description,

Note: If you are using the new Jack compiler with version 2.2.0 or newer you do not need the 'android-apt' plugin and can instead replace apt with annotationProcessor when declaring the compiler dependency. and have updated my Android to 2.2.2 since last time :-)

Now it works fine

Tank you both :-)

Seth Kroger
Seth Kroger
56,413 Points

Good to hear! Glad you got it working.

5 Answers

Seth Kroger
Seth Kroger
56,413 Points

Make sure you are following the the latest instructions on installing and using ButterKnife from it's GitHub page. If that doesn't solve the problem we might have to look the whole MainActivity code to get a better picture.

Mark Junge
Mark Junge
1,374 Points

This is my stormy build.gradle

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

task clean(type: Delete) {
    delete rootProject.buildDir
}

---------------------------------------------------------This is my app build.gradle----------------------------------------------------------

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "com.example.ideap.stormy"
        minSdkVersion 14
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.3.0'
    compile 'com.squareup.okhttp3:okhttp:3.4.1'
    compile 'com.jakewharton:butterknife:8.4.0'
}

-------------------------------------------------------This is my code from main-------------------------------------------------------------

package com.example.ideap.stormy;

import android.app.DownloadManager;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.nfc.Tag;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import butterknife.BindView;
import butterknife.ButterKnife;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {

    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.humidityValue) TextView mHumidityValue;
    @BindView(R.id.precipValue) TextView mPrecipValue;
    @BindView(R.id.summaryLabel) TextView mSummaryLabel;
    @BindView(R.id.iconImageView) ImageView mIconImageView;


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

        String apiKey = "78c0cc91ee5bab1d0b13f699f08459ef";
        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(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, R.string.Network_Unavailable_message, Toast.LENGTH_LONG).show();
        }
        Log.d(TAG, "Main UI Code is running!" );
    }

    private void updateDisplay() {

        mTemperatureLabel.setText(mCurrentWeather.getTemperature() + "");
      // mTimeLabel.setText(" At " + mCurrentWeather.getFormatedTime() + " it will be ");
    }

    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"));
        currentweather.setTimeZone(timezone);

        Log.d(TAG, currentweather.getFormatedTime());

        return 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");

    }
}

--------------------note related to: mTemperatureLabel.setText(mCurrentWeather.getTemperature()--------------------- Do not concatenate text displayed with setText. Use resource string with placeholders. less... (Ctrl+F1)

When calling TextView#setText

  • Never call Number#toString() to format numbers; it will not handle fraction separators and locale-specific digits properly. Consider using String#format with proper format specifications (%d or %f) instead.
  • Do not pass a string literal (e.g. "Hello") to display text. Hardcoded text can not be properly translated to other languages. Consider using Android resource strings instead.
  • Do not build messages by concatenating text chunks. Such messages can not be properly translated.

Hopefully this can bring a better picture of my situation

btw. Thanks a lot ;-)

[mod edit - code formatting]

Seth Kroger
Seth Kroger
56,413 Points

You got most of the butterknife configuration right but you're still missing the butterknife-compiler dependency. Once you add that, sync gradle and rebuild it should be fine. The other messages are warnings about best practice but they shouldn't affect your app being able to run.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.3.0'
    compile 'com.squareup.okhttp3:okhttp:3.4.1'
    compile 'com.jakewharton:butterknife:8.4.0'
    apt 'com.jakewharton:butterknife-compiler:8.4.0'  // <- add this line
}
Mark Junge
Mark Junge
1,374 Points

When i try to add the line: apt 'com.jakewharton:butterknife-compiler:8.4.0'

Then this occurs Error:(30, 0) Could not find method apt() for arguments [com.jakewharton:butterknife-compiler:8.4.0] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler. <a href="openFile:C:\Users\ideap\Downloads\WeeDo 2.0\Stormy\app\build.gradle">Open File</a>

Hope it still makes sense for you, so I can do something else to make it work.

TNX again, I really appreciate it :-)

Seth Kroger
Seth Kroger
56,413 Points

Oops, I missed that you also forgot the line apply plugin: 'android-apt' in build.gradle too. It should be after the apply plugin: 'com.android.application' line.

Kevin Perez
PLUS
Kevin Perez
Courses Plus Student 8,180 Points

Module: app

 apply plugin: 'com.android.application'
 apply plugin: 'android-apt'
kris Moore
kris Moore
1,752 Points

add compile 'com.jakewharton:butterknife:8.4.0' annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0' to the module: app for the build.gradle

Emily Conroyd
Emily Conroyd
6,512 Points

This was my solution which used a bit of everyones here with a slight twist. I needed the 2nd class path in addition to the new line in the project: app.

Module: app ____________________________________________________________________

dependencies { classpath 'com.android.tools.build:gradle:1.3.0' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' <--------- needed this last line too after adding the other 3 before it built without errors }

Project: Stormy ___________________________________________________________________ apply plugin: 'com.android.application' apply plugin: 'android-apt' <-------------------------------- also added this to work with the apt 'com.jakewharton:butterknife-compiler:8.5.1'

dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile files('libs/okhttp-3.6.0.jar') testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.0.1' compile 'com.squareup.okhttp3:okhttp:3.6.0' compile('com.jakewharton:butterknife:8.5.1') { exclude module: 'support-compat' <---------------------------- to get the jakewharton to work } apt 'com.jakewharton:butterknife-compiler:8.5.1' <--------------------------

androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
})

}

You should add in build.gradle

compile 'com.jakewharton:butterknife:8.5.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'