ForecastFragment.javaSunshine Project: Daten werden nach dem Aktualisieren der App nicht aktualisiert?
// Created by vgangwar7 on 31/05/16.
public class ForecastFragment extends Fragment {
public final class BuildConfig {
public static final String OPEN_WEATHER_MAP_API_KEY = "1912b14c788b31e4f1ae441a0ceefb18";
}
private ArrayAdapter<String> forecastAdapter;
public ForecastFragment(){}
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// Add this line in order for this fragment to handle menu events
setHasOptionsMenu(true);
updateWeather();
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Inflate the menu; this adds items to the action bar if it is present.
inflater.inflate(R.menu.forecastfragment, menu);
}
public boolean onOptionsItemSelected(MenuItem menuItem) {
int id = menuItem.getItemId();
if (id == R.id.action_refresh) {
FetchWeatherTask weatherTask = new FetchWeatherTask();
weatherTask.execute("110085");
return true;
}
return super.onOptionsItemSelected(menuItem);
}
private void updateWeather() {
FetchWeatherTask weatherTask = new FetchWeatherTask();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
String location = preferences.getString(getString(R.string.pref_location_key),
getString(R.string.pref_location_default));
weatherTask.execute(location);
}
public void onStart() {
super.onStart();
updateWeather();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
String[] forecastArray =
{"Today - Sunny - 88/63",
"Tomorrow - Foggy - 70/40",
"Weds - Cloudy - 72/63",
"Thurs - Asteroids - 75/65",
"Fri - Heavy Rain - 65/56",
"Sat - HELP TRAPPED IN WEATHERSITUATION - 65/51",
"Sun - Sunny - 88/68"};
List<String> weekForecast = new ArrayList<String>(Arrays.asList(forecastArray));
forecastAdapter = new ArrayAdapter<>(getActivity(),R.layout.list_item_forecast, R.id.list_item_forecast_textview, weekForecast);
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
ListView listView = (ListView) rootView.findViewById(R.id.listview_forecast);
listView.setAdapter(forecastAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
Toast.makeText(getActivity(), forecastAdapter.getItem(position), Toast.LENGTH_SHORT).show();
}
});
return rootView;
}
public class FetchWeatherTask extends AsyncTask<String, Void, String[]> {
private final String TAG = FetchWeatherTask.class.getSimpleName();
String format = "json";
String units = "metric";
final int numDays = 7;
private String getReadableDateString(long time) {
// Because the API returns a unix timestamp (measured in seconds),
// it must be converted to milliseconds in order to be converted to valid date.
SimpleDateFormat shortenedDateFormat = new SimpleDateFormat("EEE MMM dd");
return shortenedDateFormat.format(time);
}
/**
* Take the String representing the complete forecast in JSON Format and
* pull out the data we need to construct the Strings needed for the wireframes.
*
* Fortunately parsing is easy: constructor takes the JSON string and converts it
* into an Object hierarchy for us.
*/
//Prepare the weather high/lows for presentation.
private String formatHighLows(double high, double low) {
// For presentation, assume the user doesn't care about tenths of a degree.
long roundedHigh = Math.round(high);
long roundedLow = Math.round(low);
String highLowStr = roundedHigh + "/" + roundedLow;
return highLowStr;
}
/**
* Take the String representing the complete forecast in JSON Format and
* pull out the data we need to construct the Strings needed for the wireframes.
*
* Fortunately parsing is easy: constructor takes the JSON string and converts it
* into an Object hierarchy for us.
*/
private String[] getWeatherDataFromJson(String forecastJsonStr, int numDays)
throws JSONException {
// These are the names of the JSON objects that need to be extracted.
final String OWM_LIST = "list";
final String OWM_WEATHER = "weather";
final String OWM_TEMPERATURE = "temp";
final String OWM_MAX = "max";
final String OWM_MIN = "min";
final String OWM_DESCRIPTION = "main";
JSONObject forecastJson = new JSONObject(forecastJsonStr);
JSONArray weatherArray = forecastJson.getJSONArray(OWM_LIST);
String[] resultStrs = new String[numDays];
for(int i = 0; i < weatherArray.length(); i++) {
// For now, using the format "Day, description, hi/low"
String day;
String description;
String highAndLow;
// Get the JSON object representing the day
JSONObject dayForecast = weatherArray.getJSONObject(i);
//create a Gregorian Calendar, which is in current date
GregorianCalendar gc = new GregorianCalendar();
//add i dates to current date of calendar
gc.add(GregorianCalendar.DATE, i);
//get that date, format it, and "save" it on variable day
Date time = gc.getTime();
SimpleDateFormat shortenedDateFormat = new SimpleDateFormat("EEE MMM dd");
day = shortenedDateFormat.format(time);
// description is in a child array called "weather", which is 1 element long.
JSONObject weatherObject = dayForecast.getJSONArray(OWM_WEATHER).getJSONObject(0);
description = weatherObject.getString(OWM_DESCRIPTION);
// Temperatures are in a child object called "temp". Try not to name variables
// "temp" when working with temperature. It confuses everybody.
JSONObject temperatureObject = dayForecast.getJSONObject(OWM_TEMPERATURE);
double high = temperatureObject.getDouble(OWM_MAX);
double low = temperatureObject.getDouble(OWM_MIN);
highAndLow = formatHighLows(high, low);
resultStrs[i] = day + " - " + description + " - " + highAndLow;
}
for (String s : resultStrs) {
Log.v("FetchWeatherTask", "Forecast entry: " + s);
}
return resultStrs;
}
@Override
protected String[] doInBackground(String... params) {
if (params.length == 0) {
return null;
}
//These two needed to be declared outside try catch block
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String forecastJsonStr = null;
try {
// Construct the URL for the OpenWeatherMap query
// Possible parameters are avaiable at OWM's forecast API page, at
// http://openweathermap.org/API#forecast
final String FORECAST_BASE_URL = "http://api.openweathermap.org/data/2.5/forecast/daily?";
final String QUERY_PARAM = "q";
final String FORMAT_PARAM = "mode";
final String UNITS_PARAM = "units";
final String DAYS_PARAM = "cnt";
final String APPID_PARAM = "APPID";
Uri builtUri = Uri.parse(FORECAST_BASE_URL).buildUpon()
.appendQueryParameter(QUERY_PARAM, params[0])
.appendQueryParameter(FORMAT_PARAM, format)
.appendQueryParameter(UNITS_PARAM, units)
.appendQueryParameter(DAYS_PARAM, Integer.toString(numDays))
.appendQueryParameter(APPID_PARAM, BuildConfig.OPEN_WEATHER_MAP_API_KEY)
.build();
URL url = new URL(builtUri.toString());
Log.v(TAG, "Built URI " + builtUri.toString());
// Create the request to OpenWeatherMap, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
// Create the request to OpenWeatherMap, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
forecastJsonStr = buffer.toString();
} catch (IOException e) {
Log.e("ForecastFragment", "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
return null;
} finally
{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("ForecastFragment", "Error closing stream", e);
}
}
}
try{
getWeatherDataFromJson(forecastJsonStr, numDays);
}catch (JSONException e){
Log.e(TAG ,e.getMessage(), e);
e.printStackTrace();
}
return null;
}
@Override
public void onPostExecute(String[] result) {
if (result != null) {
forecastAdapter.clear();
for (String dayForecastStr : result) {
forecastAdapter.addAll(dayForecastStr);
}
forecastAdapter.notifyDataSetChanged();
}
}
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity
{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new ForecastFragment()).commit();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
if (id == R.id.action_refresh) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
aber meine logcat, ich bin in der Lage, die abgerufenen Daten aus der API und es gibt keine Fehler zu sehen im Code. LogCat -
06-04 16: 11: 31,432 3.730-3.769/com.example.vgangwar7.sunshine V/FetchWeatherTask: Prognose Eintrag: So 05 Juni - Clear - 43/31 04.06 16.11: 31.432 3730-3769/com.beispiel.vgangwar7.sunshine V/FetchWeatherTask: Prognoseeintrag: Mo Jun 06 - Löschen - 40/26 06-04 16: 11: 31.432 3730-3769/com.beispiel.vgangwar7.sunshine V/FetchWeatherTask: Vorhersageeintrag: Di Jun 07 - Löschen - 39/28 06-04 16: 11: 31.432 3730-3769/com.beispiel.vgangwar7.sunshine V/FetchWeatherTask: Vorhersageeintrag: Mi Jun 08 - Löschen - 39/26 06-04 16: 11: 31.432 3730-3769/com.beispiel.vgangwar7.sunshine V/FetchWeatherTask: Vorhersageeintrag: Do Jun 09 - Löschen - 41/27 06-04 16: 11: 31.432 3730-3769/com .beispiel.vgangwar7.sunshine V/FetchWeatherTask: Prognose Eintrag: Fr 10. Juni - Regen - 39/26
I Wetterdaten glauben holen ist async Aufgabe . Ist es möglich, dass Sie das Layout laden, bevor die Aufgabe tatsächlich abgeschlossen ist? Ist es möglich, .get() bei Ihrer Ausführung aufzurufen? Wenn ja, tue dies, das stellt sicher, dass es vollständig ist, bevor zur nächsten Ausführung gesprungen wird. Beispiel: weatherTask.execute ("110085"). get(); – Jimmy
Was möchten Sie eigentlich in der App sehen? Ihre Frage besagt, dass die Daten nach der Aktualisierung nicht aktualisiert werden. In der doInBackground-Methode liest man jedoch einfach die Wetterdaten für die nächsten 7 Tage täglich - so wird es sowieso nicht viel ändern (außer dass man die App am nächsten Tag aktualisiert). – Christian
@Jimmy Die gefälschten Daten, die ich verwendet habe, werden zuerst angezeigt. Also, nach dem Klicken auf die Schaltfläche Aktualisieren wechselt zu onOptionsItemSelected, wo es eine neue AsyncTask abrufen P.S - Ich habe die Logcat –