Skip to content
Permalink
Browse files

Done S0905-MoreDetails

  • Loading branch information
Gina
Gina committed Nov 17, 2017
1 parent bff8810 commit b009edac755e6d526b45e217a0363f78c4b0367c
@@ -33,7 +33,10 @@
import com.example.android.sunshine.utilities.SunshineDateUtils;
import com.example.android.sunshine.utilities.SunshineWeatherUtils;

public class DetailActivity extends AppCompatActivity {
import static android.transition.Fade.IN;

public class DetailActivity extends AppCompatActivity implements
LoaderManager.LoaderCallbacks<Cursor> {
// TODO (21) Implement LoaderManager.LoaderCallbacks<Cursor>

/*
@@ -43,38 +46,96 @@
private static final String FORECAST_SHARE_HASHTAG = " #SunshineApp";

// TODO (18) Create a String array containing the names of the desired data columns from our ContentProvider
// TODO (19) Create constant int values representing each column name's position above
// TODO (20) Create a constant int to identify our loader used in DetailActivity
/*
* The columns of data that we are interested in displaying within our DetailActivity's
* weather display.
*/
public static final String[] WEATHER_DETAIL_PROJECTION = {
WeatherContract.WeatherEntry.COLUMN_DATE,
WeatherContract.WeatherEntry.COLUMN_MAX_TEMP,
WeatherContract.WeatherEntry.COLUMN_MIN_TEMP,
WeatherContract.WeatherEntry.COLUMN_HUMIDITY,
WeatherContract.WeatherEntry.COLUMN_PRESSURE,
WeatherContract.WeatherEntry.COLUMN_WIND_SPEED,
WeatherContract.WeatherEntry.COLUMN_DEGREES,
WeatherContract.WeatherEntry.COLUMN_WEATHER_ID
};

// TODO (19) Create constant int values representing each column name's position above
/*
* We store the indices of the values in the array of Strings above to more quickly be able
* to access the data from our query. If the order of the Strings above changes, these
* indices must be adjusted to match the order of the Strings.
*/
public static final int INDEXT_WEATHER_DATE = 0;
public static final int INDEXT_WEATHER_MAX_TEMP = 1;
public static final int INDEXT_WEATHER_MIN_TEMP = 2;
public static final int INDEXT_WEATHER_HUMIDITY = 3;
public static final int INDEXT_WEATHER_PRESSURE = 4;
public static final int INDEXT_WEATHER_WIND_SPEED = 5;
public static final int INDEXT_WEATHER_DEGREES = 6;
public static final int INDEXT_WEATHER_CONDITION_ID = 7;

// TODO (20) Create a constant int to identify our loader used in DetailActivity
/*
* This ID will be used to identify the Loader responsible for loading the weather details
* for a particular day. In some cases, one Activity can deal with many Loaders. However, in
* our case, there is only one. We will still use this ID to initialize the loader and create
* the loader for best practice. Please note that 353 was chosen arbitrarily. You can use
* whatever number you like, so long as it is unique and consistent.
*/
private static final int ID_DETAIL_LOADER = 520;

/* A summary of the forecast that can be shared by clicking the share button in the ActionBar */
private String mForecastSummary;

// TODO (15) Declare a private Uri field called mUri
private Uri mUri;

// TODO (10) Remove the mWeatherDisplay TextView declaration
private TextView mWeatherDisplay;
//private TextView mWeatherDisplay;

// TODO (11) Declare TextViews for the date, description, high, low, humidity, wind, and pressure
private TextView mDateView;
private TextView mDescriptionView;
private TextView mHighTemperatureView;
private TextView mLowTemperatureView;
private TextView mHumidityView;
private TextView mWindView;
private TextView mPressureView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
// TODO (12) Remove mWeatherDisplay TextView
mWeatherDisplay = (TextView) findViewById(R.id.tv_display_weather);
//mWeatherDisplay = (TextView) findViewById(R.id.tv_display_weather);
// TODO (13) Find each of the TextViews by ID
mDateView = (TextView) findViewById(R.id.date);
mDescriptionView = (TextView)findViewById(R.id.weather_description);
mHighTemperatureView = (TextView)findViewById(R.id.high_temperature);
mLowTemperatureView = (TextView)findViewById(R.id.low_temperature);
mHumidityView = (TextView)findViewById(R.id.humidity);
mWindView = (TextView)findViewById(R.id.wind);
mPressureView = (TextView)findViewById(R.id.pressure);

// TODO (14) Remove the code that checks for extra text
Intent intentThatStartedThisActivity = getIntent();
if (intentThatStartedThisActivity != null) {
if (intentThatStartedThisActivity.hasExtra(Intent.EXTRA_TEXT)) {
mForecastSummary = intentThatStartedThisActivity.getStringExtra(Intent.EXTRA_TEXT);
mWeatherDisplay.setText(mForecastSummary);
}
}
// Intent intentThatStartedThisActivity = getIntent();
// if (intentThatStartedThisActivity != null) {
// if (intentThatStartedThisActivity.hasExtra(Intent.EXTRA_TEXT)) {
// mForecastSummary = intentThatStartedThisActivity.getStringExtra(Intent.EXTRA_TEXT);
// mWeatherDisplay.setText(mForecastSummary);
// }
// }

// TODO (16) Use getData to get a reference to the URI passed with this Activity's Intent
// TODO (17) Throw a NullPointerException if that URI is null
mUri = getIntent().getData();
if(mUri == null) throw new NullPointerException("URI for DetailActivity cannot be null");
//
// TODO (35) Initialize the loader for DetailActivity
/* This connects our Activity into the loader lifecycle. */
getSupportLoaderManager().initLoader(ID_DETAIL_LOADER, null, this);
}

/**
@@ -144,21 +205,175 @@ private Intent createShareForecastIntent() {
return shareIntent;
}


// TODO (22) Override onCreateLoader
// TODO (23) If the loader requested is our detail loader, return the appropriate CursorLoader
/**
* Creates and returns a CursorLoader that loads the data for our URI and stores it in a Cursor.
*
* @param loaderId The loader ID for which we need to create a loader
* @param loaderArgs Any arguments supplied by the caller
*
* @return A new Loader instance that is ready to start loading.
*/
@Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle loaderArgs) {

// TODO (23) If the loader requested is our detail loader, return the appropriate CursorLoader
switch (loaderId){
case ID_DETAIL_LOADER:
return new CursorLoader(this,
mUri,
WEATHER_DETAIL_PROJECTION,
null,
null,
null);
default:
throw new RuntimeException("Loader Not Implemented: "+loaderId);
}
}

// TODO (24) Override onLoadFinished
/**
* Runs on the main thread when a load is complete. If initLoader is called (we call it from
* onCreate in DetailActivity) and the LoaderManager already has completed a previous load
* for this Loader, onLoadFinished will be called immediately. Within onLoadFinished, we bind
* the data to our views so the user can see the details of the weather on the date they
* selected from the forecast.
*
* @param loader The cursor loader that finished.
* @param data The cursor that is being returned.
*/
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
/*
* Before we bind the data to the UI that will display that data, we need to check the
* cursor to make sure we have the results that we are expecting. In order to do that, we
* check to make sure the cursor is not null and then we call moveToFirst on the cursor.
* Although it may not seem obvious at first, moveToFirst will return true if it contains
* a valid first row of data.
*
* If we have valid data, we want to continue on to bind that data to the UI. If we don't
* have any data to bind, we just return from this method.
*/
// TODO (25) Check before doing anything that the Cursor has valid data
boolean cursorHasValidData = false;
if(data != null && data.moveToFirst()){
/* We have valid data, continue on to bind the data to the UI*/
cursorHasValidData = true;
}

if(!cursorHasValidData){
/* No data to display, simply return and do nothing */
return;
}

// TODO (26) Display a readable data string
/****************
* Weather Date *
****************/
/*
* Read the date from the cursor. It is important to note that the date from the cursor
* is the same date from the weather SQL table. The date that is stored is a GMT
* representation at midnight of the date when the weather information was loaded for.
*
* When displaying this date, one must add the GMT offset (in milliseconds) to acquire
* the date representation for the local date in local time.
* SunshineDateUtils#getFriendlyDateString takes care of this for us.
*/
long localDataMidnightGmt = data.getLong(INDEXT_WEATHER_DATE);
String dataText = SunshineDateUtils.getFriendlyDateString(this, localDataMidnightGmt, true);
mDateView.setText(dataText);

// TODO (27) Display the weather description (using SunshineWeatherUtils)
/***********************
* Weather Description *
***********************/
/* Read weather condition ID from the cursor (ID provided by Open Weather Map) */
int weatherId = data.getInt(INDEXT_WEATHER_CONDITION_ID);
/* Use the weatherId to obtain the proper description */
String description = SunshineWeatherUtils.getStringForWeatherCondition(this, weatherId);
mDescriptionView.setText(description);

// TODO (28) Display the high temperature
/**************************
* High (max) temperature *
**************************/
/* Read high temperature from the cursor (in degrees celsius) */
double highInCelsius = data.getDouble(INDEXT_WEATHER_MAX_TEMP);
/*
* If the user's preference for weather is fahrenheit, formatTemperature will convert
* the temperature. This method will also append either °C or °F to the temperature
* String.
*/
String highString = SunshineWeatherUtils.formatTemperature(this, highInCelsius);
mHighTemperatureView.setText(highString);

// TODO (29) Display the low temperature
/*************************
* Low (min) temperature *
*************************/
/* Read low temperature from the cursor (in degrees celsius) */
double lowInCelsius = data.getDouble(INDEXT_WEATHER_MIN_TEMP);
String lowString = SunshineWeatherUtils.formatTemperature(this, lowInCelsius);
mLowTemperatureView.setText(lowString);

// TODO (30) Display the humidity
/************
* Humidity *
************/
float humidity = data.getFloat(INDEXT_WEATHER_HUMIDITY);
String humidityString = getString(R.string.format_humidity, humidity);
mHumidityView.setText(humidityString);

// TODO (31) Display the wind speed and direction
/****************************
* Wind speed and direction *
****************************/
/* Read wind speed (in MPH) and direction (in compass degrees) from the cursor */
float windSpeed = data.getFloat(INDEXT_WEATHER_WIND_SPEED);
float winDirection = data.getFloat(INDEXT_WEATHER_DEGREES);
String windString = SunshineWeatherUtils.getFormattedWind(this, windSpeed, winDirection);

mWindView.setText(windString);

// TODO (32) Display the pressure
// TODO (33) Store a forecast summary in mForecastSummary
/************
* Pressure *
************/
float pressure = data.getFloat(INDEXT_WEATHER_PRESSURE);
/*
* Format the pressure text using string resources. The reason we directly access
* resources using getString rather than using a method from SunshineWeatherUtils as
* we have for other data displayed in this Activity is because there is no
* additional logic that needs to be considered in order to properly display the
* pressure.
*/
String pressureString = getString(R.string.format_pressure, pressure);
mPressureView.setText(pressureString);

// TODO (33) Store a forecast summary in mForecastSummary
/* Store the forecast summary String in our forecast summary field to share later */
mForecastSummary = String.format("%s - %s - %s/%s",
dataText, description, highString, lowString);
}

// TODO (34) Override onLoaderReset, but don't do anything in it yet
/**
* Called when a previously created loader is being reset, thus making its data unavailable.
* The application should at this point remove any references it has to the Loader's data.
* Since we don't store any of this cursor's data, there are no references we need to remove.
*
* @param loader The Loader that is being reset.
*/
@Override
public void onLoaderReset(Loader<Cursor> loader) {

}







}
@@ -49,7 +49,7 @@
*/
public interface ForecastAdapterOnClickHandler {
// TODO (36) Refactor onClick to accept a long as its parameter rather than a String
void onClick(String weatherForDay);
void onClick(long date);
}

private Cursor mCursor;
@@ -178,8 +178,10 @@ void swapCursor(Cursor newCursor) {
@Override
public void onClick(View v) {
// TODO (37) Instead of passing the String for the clicked item, pass the date from the cursor
String weatherForDay = weatherSummary.getText().toString();
mClickHandler.onClick(weatherForDay);
int adapterPosition = getAdapterPosition();
mCursor.moveToPosition(adapterPosition);
long dateInMillis = mCursor.getLong(MainActivity.INDEX_WEATHER_DATE);
mClickHandler.onClick(dateInMillis);
}
}
}
@@ -38,8 +38,8 @@
import com.example.android.sunshine.utilities.FakeDataUtils;

public class MainActivity extends AppCompatActivity implements
LoaderManager.LoaderCallbacks<Cursor>,
ForecastAdapter.ForecastAdapterOnClickHandler {
ForecastAdapter.ForecastAdapterOnClickHandler,
LoaderManager.LoaderCallbacks<Cursor>{

private final String TAG = MainActivity.class.getSimpleName();

@@ -258,20 +258,28 @@ public void onLoaderReset(Loader<Cursor> loader) {
mForecastAdapter.swapCursor(null);
}

// TODO (38) Refactor onClick to accept a long instead of a String as its parameter
// TODO (38) Refactor onClick to accept a long instead of a String as its paramete


/**
* This method is for responding to clicks from our list.
*
* @param weatherForDay String describing weather details for a particular day
* @param date Normalized UTC time that represents the local date of the weather in GMT time.
* @see WeatherContract.WeatherEntry#COLUMN_DATE
*/
@Override
public void onClick(String weatherForDay) {
public void onClick(long date) {
// Context context = this;
// Class destinationClass = DetailActivity.class;
// Intent intentToStartDetailActivity = new Intent(context, destinationClass);
// intentToStartDetailActivity.putExtra(Intent.EXTRA_TEXT, weatherForDay);
// startActivity(intentToStartDetailActivity);
Intent weatherDetailIntent = new Intent(MainActivity.this, DetailActivity.class);

// TODO (39) Refactor onClick to build a URI for the clicked date and and pass it with the Intent using setData
Context context = this;
Class destinationClass = DetailActivity.class;
Intent intentToStartDetailActivity = new Intent(context, destinationClass);
intentToStartDetailActivity.putExtra(Intent.EXTRA_TEXT, weatherForDay);
startActivity(intentToStartDetailActivity);
Uri uriForDateClicked = WeatherContract.WeatherEntry.buildWeatherUriWithDate(date);
weatherDetailIntent.setData(uriForDateClicked);
startActivity(weatherDetailIntent);
}

/**
@@ -346,4 +354,5 @@ public boolean onOptionsItemSelected(MenuItem item) {

return super.onOptionsItemSelected(item);
}

}

0 comments on commit b009eda

Please sign in to comment.
You can’t perform that action at this time.