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 Android Lists and Adapters (2015) Lists with RecyclerViews Using a Layout Manager

Stormy is crashing when I click on the Hourly Button.

Hello everyone TheBigOso here.

Im having some troubles with the last part in making this app.

When I click on the Hourly Button my program crashes.

I made a youtube video to show whats going on. https://www.youtube.com/watch?v=6CExClOqzY4

Ive also made my project available on github.com https://github.com/TheBigOso/Stormy

Thanks,

TheBigOso

Here is my logcat

10-09 11:54:53.947 13649-13671/com.example.ryan.stormy I/MainActivity: From JSON America/Los_Angeles
10-09 11:54:53.948 13649-13671/com.example.ryan.stormy D/MainActivity: 11:55:AM
10-09 11:54:59.023 1273-1284/system_process I/ActivityManager: START u0 {cmp=com.example.ryan.stormy/.UI.HourlyForecastActivity (has extras)} from uid 10058 on display 0
10-09 11:54:59.089 13649-13675/com.example.ryan.stormy W/EGL_emulation: eglSurfaceAttrib not implemented
10-09 11:54:59.089 13649-13675/com.example.ryan.stormy W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xad711b00, error=EGL_SUCCESS
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy D/AndroidRuntime: Shutting down VM
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime: FATAL EXCEPTION: main
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime: Process: com.example.ryan.stormy, PID: 13649
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at com.example.ryan.stormy.adapters.HourAdapter$HourViewHolder.bindHour(HourAdapter.java:62)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at com.example.ryan.stormy.adapters.HourAdapter.onBindViewHolder(HourAdapter.java:35)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at com.example.ryan.stormy.adapters.HourAdapter.onBindViewHolder(HourAdapter.java:16)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5277)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5310)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4568)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4461)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1962)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1371)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1334)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:563)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2847)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3145)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.View.layout(View.java:16630)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.ViewGroup.layout(ViewGroup.java:5437)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1079)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.View.layout(View.java:16630)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.ViewGroup.layout(ViewGroup.java:5437)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.View.layout(View.java:16630)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.ViewGroup.layout(ViewGroup.java:5437)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.View.layout(View.java:16630)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.ViewGroup.layout(ViewGroup.java:5437)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.View.layout(View.java:16630)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.ViewGroup.layout(ViewGroup.java:5437)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.View.layout(View.java:16630)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.ViewGroup.layout(ViewGroup.java:5437)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at com.android.internal.policy.PhoneWindow$DecorView.onLayout(PhoneWindow.java:2678)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.View.layout(View.java:16630)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.ViewGroup.layout(ViewGroup.java:5437)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2171)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1931)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.Choreographer.doCallbacks(Choreographer.java:670)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.Choreographer.doFrame(Choreographer.java:606)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.os.Handler.handleCallback(Handler.java:739)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:95)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:148)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5417)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
10-09 11:54:59.110 13649-13649/com.example.ryan.stormy E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
10-09 11:54:59.127 1273-1285/system_process W/ActivityManager:   Force finishing activity com.example.ryan.stormy/.UI.HourlyForecastActivity
10-09 11:54:59.130 1273-1285/system_process W/ActivityManager:   Force finishing activity com.example.ryan.stormy/.UI.MainActivity
10-09 11:54:59.195 1273-1790/system_process I/OpenGLRenderer: Initialized EGL, version 1.4
10-09 11:54:59.230 1273-1790/system_process W/EGL_emulation: eglSurfaceAttrib not implemented
10-09 11:54:59.230 1273-1790/system_process W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0x9c5896a0, error=EGL_SUCCESS
10-09 11:54:59.638 1273-1293/system_process W/ActivityManager: Activity pause timeout for ActivityRecord{e58ef61 u0 com.example.ryan.stormy/.UI.HourlyForecastActivity t68 f}
10-09 11:54:59.793 2189-2212/com.android.launcher3 W/EGL_emulation: eglSurfaceAttrib not implemented
10-09 11:54:59.793 2189-2212/com.android.launcher3 W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xa2a4cd20, error=EGL_SUCCESS
10-09 11:55:00.142 1273-1580/system_process I/ActivityManager: Killing 2011:com.android.providers.calendar/u0a1 (adj 15): empty for 1814s
10-09 11:55:00.438 2189-2212/com.android.launcher3 W/OpenGLRenderer: Incorrectly called buildLayer on View: ShortcutAndWidgetContainer, destroying layer...
10-09 11:55:00.438 2189-2212/com.android.launcher3 W/OpenGLRenderer: Incorrectly called buildLayer on View: ShortcutAndWidgetContainer, destroying layer...
10-09 11:55:01.714 13649-13649/? I/Process: Sending signal. PID: 13649 SIG: 9
10-09 11:55:01.718 1273-1284/system_process I/WindowState: WIN DEATH: Window{354209d u0 com.example.ryan.stormy/com.example.ryan.stormy.UI.HourlyForecastActivity}
10-09 11:55:01.718 1273-1727/system_process D/GraphicsStats: Buffer count: 3
10-09 11:55:01.722 1273-1907/system_process I/ActivityManager: Process com.example.ryan.stormy (pid 13649) has died
10-09 11:55:01.726 1273-1310/system_process W/InputDispatcher: channel '3814db0 com.example.ryan.stormy/com.example.ryan.stormy.UI.MainActivity (server)' ~ Consumer closed input channel or an error occurred.  events=0x9
10-09 11:55:01.726 1273-1310/system_process E/InputDispatcher: channel '3814db0 com.example.ryan.stormy/com.example.ryan.stormy.UI.MainActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
10-09 11:55:01.726 1273-1310/system_process W/InputDispatcher: channel '354209d com.example.ryan.stormy/com.example.ryan.stormy.UI.HourlyForecastActivity (server)' ~ Consumer closed input channel or an error occurred.  events=0x9
10-09 11:55:01.726 1273-1310/system_process E/InputDispatcher: channel '354209d com.example.ryan.stormy/com.example.ryan.stormy.UI.HourlyForecastActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
10-09 11:55:01.727 1273-1284/system_process W/InputDispatcher: Attempted to unregister already unregistered input channel '354209d com.example.ryan.stormy/com.example.ryan.stormy.UI.HourlyForecastActivity (server)'
10-09 11:55:01.729 1273-1727/system_process I/WindowState: WIN DEATH: Window{3814db0 u0 com.example.ryan.stormy/com.example.ryan.stormy.UI.MainActivity}
10-09 11:55:01.729 1273-1727/system_process W/InputDispatcher: Attempted to unregister already unregistered input channel '3814db0 com.example.ryan.stormy/com.example.ryan.stormy.UI.MainActivity (server)'
10-09 11:55:01.739 1811-1811/com.google.android.gms D/ChimeraCfgMgr: Loading module com.google.android.gms.games from APK com.google.android.gms
10-09 11:55:01.741 1811-1811/com.google.android.gms D/ChimeraCfgMgr: Loading module com.google.android.gms.kids from APK com.google.android.gms
10-09 11:55:01.748 972-1289/? D/AudioFlinger: mixer(0xb4500000) throttle end: throttle time(176)
10-09 11:55:01.827 1273-1790/system_process E/Surface: getSlotFromBufferLocked: unknown buffer: 0xa20d19c0
10-09 11:55:01.833 1273-1790/system_process D/OpenGLRenderer: endAllStagingAnimators on 0x9c508200 (RippleDrawable) with handle 0xa037f7a0
10-09 11:55:01.843 1273-1307/system_process W/InputMethodManagerService: Got RemoteException sending setActive(false) notification to pid 13649 uid 10058
10-09 11:55:02.089 1273-1298/system_process W/AppOps: Finishing op nesting under-run: uid 1000 pkg android code 24 time=0 duration=0 nesting=0

Here is my build.gradle(Module:app)

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        applicationId "com.example.ryan.stormy"
        minSdkVersion 15
        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.0.1'
    compile 'com.squareup.okhttp:okhttp:2.5.0'
    compile 'com.jakewharton:butterknife:7.0.1'
    compile 'com.android.support:recyclerview-v7:23.0.1'
}

MainActivity.Java

package com.example.ryan.stormy.UI;

import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ImageView;

import com.example.ryan.stormy.R;
import com.example.ryan.stormy.weather.Current;
import com.example.ryan.stormy.weather.Day;
import com.example.ryan.stormy.weather.Forecast;
import com.example.ryan.stormy.weather.Hour;
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.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;

import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class MainActivity extends AppCompatActivity {

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

    private Forecast mForecast;



    @Bind(R.id.timeLabel) TextView mTimeLabel;
    @Bind(R.id.temperatureLabel) TextView mTemperatureLabel;
    @Bind(R.id.humidityValue) TextView mHumidityValue;
    @Bind(R.id.precipValue) TextView mPrecipValue;
    @Bind(R.id.summaryLabel) TextView mSummaryLabel;
    @Bind(R.id.iconImageView) ImageView mIconImageView;
    @Bind(R.id.refreshImageView) ImageView mRefreshImageView;
    @Bind(R.id.progressBar) ProgressBar mProgressBar;


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

        mProgressBar.setVisibility(View.INVISIBLE);

        final double latitude = 38.9400;
        final double longitude = -119.9769;

        mRefreshImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getForcast(latitude, longitude);
            }
        });

        getForcast(latitude, longitude);
        Log.d(TAG, "main UI code is running");
    }

    private void getForcast(double latitude, double longitude) {
        String apiKey = "a407596f1a5e3c1d316fce9eba373db0";

        String forcaseUrl ="https://api.forecast.io/forecast/" + apiKey + "/" + latitude + "," + longitude;

        if(isNetworkAvailable()) {

            toggleRefresh();

            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder()
                    .url(forcaseUrl)
                    .build();
            Call call = client.newCall(request);
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Request request, IOException e) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            toggleRefresh();
                        }
                    });
                    alertUserAboutError();
                }

                @Override
                public void onResponse(Response response) throws IOException {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            toggleRefresh();
                        }
                    });
                    try {
                        String jsonData = response.body().string();
                        Log.v(TAG, jsonData);
                        if (response.isSuccessful()) {
                            mForecast = parseForecastDetails(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();
        }
    }

    private void toggleRefresh() {
        if(mProgressBar.getVisibility() == View.INVISIBLE) {
            mProgressBar.setVisibility(View.VISIBLE);
            mRefreshImageView.setVisibility(View.INVISIBLE);
        }
        else{
            mProgressBar.setVisibility(View.INVISIBLE);
            mRefreshImageView.setVisibility(View.VISIBLE);
        }
    }

    private void updateDisplay() {
        Current current = mForecast.getCurrent();
        mTemperatureLabel.setText(current.getTemperature() + "");
        mTimeLabel.setText("At " + current.getFormattedTime() + " it will be");
        mHumidityValue.setText(current.getHumidity() + "");
        mPrecipValue.setText(current.getPrecipChance() + "%");
        mSummaryLabel.setText(current.getSummary());

        Drawable drawable = getResources().getDrawable(current.getIconId());
        mIconImageView.setImageDrawable(drawable);
    }

    private Forecast parseForecastDetails(String jsonData)throws JSONException{
        Forecast forecast = new Forecast();

        forecast.setCurrent(getCurrentDetails(jsonData));
        forecast.setHourlyForecast(getHourlyForecast(jsonData));
       forecast.setDailyForecast(getDailyForecast(jsonData));
        return forecast;
    }

    private Day[] getDailyForecast(String jsonData)throws JSONException {
        JSONObject forecast = new JSONObject(jsonData);
        String timezone = forecast.getString("timezone");
        JSONObject daily = forecast.getJSONObject("daily");
        JSONArray data = daily.getJSONArray("data");

        Day[] days = new Day[data.length()];

        for (int i = 0; i < data.length(); i++) {
            JSONObject jsonDay = data.getJSONObject(i);
            Day day = new Day();

            day.setSummary(jsonDay.getString("summary"));
            day.setIcon(jsonDay.getString("icon"));
            day.setTemperatureMax(jsonDay.getDouble("temperatureMax"));
            day.setTime(jsonDay.getLong("time"));
            day.setTimezone(timezone);

            days[i] = day;


        }
        return days;
    }
    private Hour[] getHourlyForecast(String jsonData)throws JSONException {
        JSONObject forecast = new JSONObject(jsonData);
        String timezone = forecast.getString("timezone");
        JSONObject hourly = forecast.getJSONObject("hourly");
        JSONArray data = hourly.getJSONArray("data");

        Hour[] hours = new Hour[data.length()];

        for( int i = 0; i < data.length(); i++){
            JSONObject jsonHour = data.getJSONObject(i);
            Hour hour = new Hour();

            hour.setSummary(jsonHour.getString("summary"));
            hour.setIcon(jsonHour.getString("icon"));
            hour.setTemperature(jsonHour.getDouble("temperature"));
            hour.setTime(jsonHour.getLong("time"));
            hour.setTimezone(timezone);

            hours[i] = hour;
        }
        return hours;
    }

    private Current 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");

        Current current = new Current();
        current.setHumidity(currently.getDouble("humidity"));
        current.setTime(currently.getLong("time"));
        current.setIcon(currently.getString("icon"));
        current.setPrecipChance(currently.getDouble("precipProbability"));
        current.setSummary(currently.getString("summary"));
        current.setTemperature(currently.getDouble("temperature"));
        current.setTimeZone(timezone);

        Log.d(TAG, current.getFormattedTime());

        return current;
    }


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

    private void alertUserAboutError() {

        AlertDialogFragment dialog = new AlertDialogFragment();
        dialog.show(getFragmentManager(),"error_dialog");
    }

    @OnClick (R.id.dailyButton)
    public void startDailyActivity(View view){
        Intent intent = new Intent(this,DailyForecastActivity.class);
        intent.putExtra(DAILY_FORECAST, mForecast.getDailyForecast());
        startActivity(intent);
    }
    @OnClick (R.id.hourlyButton)
    public void startHourlyActivity (View view){
        Intent intent = new Intent(this,HourlyForecastActivity.class);
        intent.putExtra(HOURLY_FORECAST, mForecast.getHourlyForecast());
        startActivity(intent);


    }
}

HourAdapter.java

package com.example.ryan.stormy.adapters;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.ryan.stormy.R;
import com.example.ryan.stormy.weather.Hour;

/**
 * Created by ryanr on 10/7/2015.
 */
public class HourAdapter  extends RecyclerView.Adapter<HourAdapter.HourViewHolder>{

    private Hour[] mHours;

    public HourAdapter(Hour[] hours){
        mHours = hours;

    }

    @Override
    public HourViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.hourly_list_item ,parent ,false);
        HourViewHolder viewHolder = new HourViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(HourViewHolder holder, int position) {
        holder.bindHour(mHours[position]);

    }

    @Override
    public int getItemCount() {
        return mHours.length;
    }

    public class HourViewHolder extends RecyclerView.ViewHolder{

        public TextView mTimeLabel;
        public TextView mSummaryLabel;
        public TextView mTemperatureLabel;
        public ImageView mIconImageView;

        public HourViewHolder(View itemView) {
            super(itemView);

            mTimeLabel =(TextView) itemView.findViewById(R.id.timeLabel);
            mSummaryLabel=(TextView) itemView.findViewById(R.id.summaryLabel);
            mTemperatureLabel=(TextView) itemView.findViewById(R.id.temperatureLabel);
            mIconImageView=(ImageView) itemView.findViewById(R.id.iconImageView);

        }
        public void bindHour(Hour hour){
            mTimeLabel.setText(hour.getHour());
            mSummaryLabel.setText(hour.getSummary());
            mTemperatureLabel.setText(hour.getTemperature() + "");
            mIconImageView.setImageResource(hour.getIconId());

        }
    }


}

HourlyForecastActivity.java

package com.example.ryan.stormy.UI;

import android.content.Intent;
import android.os.Parcelable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import com.example.ryan.stormy.R;
import com.example.ryan.stormy.adapters.HourAdapter;
import com.example.ryan.stormy.weather.Hour;

import java.util.Arrays;

import butterknife.Bind;
import butterknife.ButterKnife;

public class HourlyForecastActivity extends AppCompatActivity {

    private Hour[] mHours;

    @Bind(R.id.reyclerView) RecyclerView mRecyclerView;

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

        Intent intent = getIntent();
        Parcelable[] parcelables = intent.getParcelableArrayExtra(MainActivity.HOURLY_FORECAST);
        mHours = Arrays.copyOf(parcelables, parcelables.length, Hour[].class);

        HourAdapter adapter = new HourAdapter(mHours);
        mRecyclerView.setAdapter(adapter);

        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(layoutManager);

        mRecyclerView.setHasFixedSize(true);

    }
}

Hour.java

package com.example.ryan.stormy.weather;

import android.os.Parcel;
import android.os.Parcelable;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by ryanr on 10/5/2015.
 */
public class Hour implements Parcelable{
    private long mTime;
    private double mTemperature;
    private String mSummary;
    private String mIcon;
    private String mTimezone;



    public long getTime() {
        return mTime;
    }

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

    public String getSummary() {
        return mSummary;
    }

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

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

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

    public String getIcon() {
        return mIcon;
    }

    public int getIconId(){
       return Forecast.getIconId(mIcon);
    }

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

    public String getTimezone() {
        return mTimezone;
    }

    public void setTimezone(String timezone) {
        mTimezone = timezone;
    }


    public String getHour(){
        SimpleDateFormat formatter = new SimpleDateFormat("h a");
        Date date = new Date(mTime * 1000);
        return formatter.format(date);
    }


    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {

        dest.writeLong(mTime);
        dest.writeDouble(mTemperature);
        dest.writeString(mSummary);
        dest.writeString(mIcon);
        dest.writeString(mTimezone);
    }
    public Hour(){ }

    private Hour(Parcel in){
        mTime = in.readLong();
        mTemperature= in.readDouble();
        mSummary= in.readString();
        mIcon= in.readString();
        mTimezone= in.readString();
    }

    public static final Creator<Hour> CREATOR = new Creator<Hour>() {
        @Override
        public Hour createFromParcel(Parcel source) {
            return new Hour(source);
        }

        @Override
        public Hour[] newArray(int size) {
            return new Hour[size];
        }
    };
//
}
Talmage Shill
Talmage Shill
Courses Plus Student 7,593 Points

Hey Ryan, I'm looking through your logcat file and I see that you're getting a null pointer exception. This means you are trying to use something that doesn't exist yet. I'm going to download your code from github and try and find whats causing the exception. This will probably take a while.

Thank you Talmage

Jordan Ernst
Jordan Ernst
5,121 Points

i have the same code as you and my version of android studio keeps putting lines through methods. example. getDrawable() it keeps getting a line through it and saying deprecated api. i can't run the debugger and it doesn't show any errors in other places.

2 Answers

Talmage Shill
PLUS
Talmage Shill
Courses Plus Student 7,593 Points

I believe I figured it out! It is actually a super simple mistake. On line 55 of HourAdapter.java you have:

mSummaryLabel = (TextView) itemView.findViewById(R.id.summaryLabel);

which looks correct; However, when I went to hourly_list_item.xml I found SummaryLabel (capital S) and not summaryLabel. summaryLabel is defined in the activity_main.xml. Change this line to this and it should work:

mSummaryLabel = (TextView) itemView.findViewById(R.id.SummaryLabel);

Let me know if this works.

Your a Rock Star!!!.... Thank you so much. i totally overlooked this. wow. you saved me.

TheBigOso

If anyone Wants to overlook my project im going to leave it up on github. https://github.com/TheBigOso/Stormy