2015-10-13 80 views
0

我已成功實施android陽光應用程序進行天氣預報。它工作正常。Android陽光應用程序(udacity)空白列表視圖

我通過更新應用程序進行了一些更新和我目前的版本是:6.7.1.0(KHJMICH)和操作系統是4.4.4KTU84P和我的手機是redmii 2

現在一個問題就是快到了,我完全不知道這是怎麼發生。每當我運行我的應用程序,就會出現一個空白的列表視圖。

所以基本上我使用發送到openweathermap的http查詢獲取json格式的天氣預報,然後填充listview。

我沒有對我的源代碼進行修改,它是相同的。這是什麼讓我最困惑

這是填充listview的代碼。 for循環之後

package com.example.hp.weather_app; 

import android.content.Context; 
import android.content.Intent; 
import android.content.SharedPreferences; 
import android.net.Uri; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.preference.PreferenceManager; 
import android.support.v4.app.Fragment; 
import android.text.format.Time; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.Menu; 
import android.view.MenuInflater; 
import android.view.MenuItem; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.AdapterView; 
import android.widget.ArrayAdapter; 
import android.widget.ListView; 
import android.widget.Toast; 

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

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.net.HttpURLConnection; 
import java.net.URL; 
import java.text.SimpleDateFormat; 
import java.util.ArrayList; 

/** 
* Created by hp on 20-06-2015. 
*/ 

public class MainActivityFragment extends Fragment { 
    static ArrayAdapter<String> weather_adapter; 
    public MainActivityFragment() { 
    } 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setHasOptionsMenu(true); 
    } 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     View rootview = inflater.inflate(R.layout.fragment_main, container, false); 
     ArrayList<String> x = new ArrayList<String>(); 
     weather_adapter = new ArrayAdapter<String>(getActivity(), R.layout.list_item_forecast, R.id.list_item_forecast_textview, x); 
     final ListView listview = (ListView) rootview.findViewById(R.id.list_view_forecast); 
     listview.setAdapter(weather_adapter); 
     listview.setOnItemClickListener(new AdapterView.OnItemClickListener() 
     { 
      public void onItemClick(AdapterView<?> adapterView,View view,int i,long l) 
      { 
       String msg=(String)listview.getItemAtPosition(i); 
       Intent it=new Intent(getActivity(),Detail_Activity.class).putExtra(Intent.EXTRA_TEXT,msg); 
       startActivity(it); 
      } 
     }); 
     return rootview; 
    } 
    public void onCreateOptionsMenu(Menu menu,MenuInflater inflater) 
    { 
     inflater.inflate(R.menu.forecast_fragment, menu); 
    } 
    public void onStart() 
    { 
     super.onStart(); 
     updateweather(); 
    } 
    private void updateweather() 
    { 
     FetchWeatherTask w=new FetchWeatherTask(getActivity()); 
     SharedPreferences prefs= PreferenceManager.getDefaultSharedPreferences(getActivity()); 
     String location = prefs.getString(getString(R.string.pref_location_key), 
       getString(R.string.pref_location_default)); 
     w.execute(location); 
    } 
    public boolean onOptionsItemSelected(MenuItem item) 
    { 
     int id=item.getItemId(); 
     if(id==R.id.action_refresh) { 
      FetchWeatherTask w=new FetchWeatherTask(getActivity()); 
      SharedPreferences prefs= PreferenceManager.getDefaultSharedPreferences(getActivity()); 
      String location = prefs.getString(getString(R.string.pref_location_key), 
        getString(R.string.pref_location_default)); 
      w.execute(location); 
      return true; 
     } 
     if (id == R.id.action_settings) { 
      startActivity(new Intent(getActivity(), SettingsActivity.class)); 
      return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 
} 
class FetchWeatherTask extends AsyncTask<String ,Context,String []> 
{private Context mContext; 
    public FetchWeatherTask(Context context) { 
     this.mContext = context; 
    } 
    @Override 
    protected String [] doInBackground(String []params) 
    { 
     HttpURLConnection urlConnection = null; 
     BufferedReader reader = null; 
     String forecastJsonStr = null; 
     String format="json"; 
     String units="metric"; 
     int numDays=7; 
     try { 
      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"; 
      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)) 
        .build(); 
      URL url = new URL(builtUri.toString()); 
      urlConnection = (HttpURLConnection) url.openConnection(); 
      urlConnection.setRequestMethod("GET"); 
      urlConnection.connect(); 
      InputStream inputStream = urlConnection.getInputStream(); 
      StringBuffer buffer = new StringBuffer(); 
      if (inputStream == null) { 
       return null; 
      } 
      reader = new BufferedReader(new InputStreamReader(inputStream)); 
      String line; 
      while ((line = reader.readLine()) != null) { 
       buffer.append(line + "\n"); 
      } 
      if (buffer.length() == 0) { 
       return null; 
      } 
      forecastJsonStr = buffer.toString(); 
     } catch (IOException e) { 
      Log.e("PlaceholderFragment", "Error ", e); 
      return null; 
     } finally{ 
      if (urlConnection != null) { 
       urlConnection.disconnect(); 
      } 
      if (reader != null) { 
       try { 
        reader.close(); 
       } catch (final IOException e) { 
        Log.e("PlaceholderFragment", "Error closing stream", e); 
       } 
      } 
     } 

     try 
     { 
      return getWeatherDataFromJson(forecastJsonStr,numDays); 
     } 
     catch(JSONException e) 
     { 

     } 
     return null; 
    } 
    protected void onPostExecute(String[] result) { 
     if (result != null) { 
      MainActivityFragment.weather_adapter.clear(); 
      for(String dayForecastStr : result) { 
       MainActivityFragment.weather_adapter.add(dayForecastStr); 
      } 
     } 
    } 
    private String getReadableDateString(long time){ 
     SimpleDateFormat shortenedDateFormat = new SimpleDateFormat("EEE MMM dd"); 
     return shortenedDateFormat.format(time); 
    } 
    private String[] getWeatherDataFromJson(String forecastJsonStr, int numDays) 
      throws JSONException 
    { 
     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); 
     Time dayTime = new Time(); 
     dayTime.setToNow(); 
     int julianStartDay = Time.getJulianDay(System.currentTimeMillis(), dayTime.gmtoff); 
     dayTime = new Time(); 
     String[] resultStrs = new String[numDays]; 
     for(int i = 0; i < weatherArray.length(); i++) { 
      String day; 
      String description; 
      String highAndLow; 
      JSONObject dayForecast = weatherArray.getJSONObject(i); 
      long dateTime; 
      dateTime = dayTime.setJulianDay(julianStartDay+i); 
      day = getReadableDateString(dateTime); 
      JSONObject weatherObject = dayForecast.getJSONArray(OWM_WEATHER).getJSONObject(0); 
      description = weatherObject.getString(OWM_DESCRIPTION); 
      JSONObject temperatureObject = dayForecast.getJSONObject(OWM_TEMPERATURE); 
      double high = temperatureObject.getDouble(OWM_MAX); 
      double low = temperatureObject.getDouble(OWM_MIN); 
      String HL=formatHighLows(high,low); 
      resultStrs[i] = day + " - " + description + " - " +HL; 
     } 
     return resultStrs; 
    } 
    public String formatHighLows(double high, double low) { 
     MainActivityFragment obj=new MainActivityFragment(); 

     SharedPreferences sharedPrefs=PreferenceManager.getDefaultSharedPreferences(mContext); 
     String unitType=sharedPrefs.getString(mContext.getString(R.string.pref_units_key),mContext.getString(R.string.pref_units_metric)); 
     if(unitType.equals(mContext.getString(R.string.pref_units_imperial))) 
     { 
      high=(high*1.8)+32; 
      low=(low*1.8)+32; 
     } 
     else if(!unitType.equals(mContext.getString(R.string.pref_units_metric))) 
     { 
      Toast.makeText(mContext,"invalid unit",Toast.LENGTH_SHORT).show(); 
     } 
     long roundedHigh = Math.round(high); 
     long roundedLow = Math.round(low); 
     String str= roundedHigh+"/"+roundedLow; 
     return str; 
    } 
} 

回答

3

openweathermap API現在需要一個API密鑰。這在上週改變了。如果您最近運行你的應用程序,你會更容易看到一個錯誤日誌中:

java.io.FileNotFoundException:http://api.openweathermap.org/data/2.5/forecast/daily?q= ...

如果你抓住了這個例外,例如,它並沒有得到記錄,你可能會得到一個空白的列表視圖,因爲沒有值填充它。

+0

非常感謝。你也可以告訴我如何獲得鑰匙? –

+0

這裏是鏈接[link](http://openweathermap.org/appid)。您可以免費註冊並從註冊後的頁面複製密鑰。 –

0

待辦事項notifyDataSetChanged()數組適配器上後在onPostExecute()方法。

 if (result != null) { 
      MainActivityFragment.weather_adapter.clear(); 
      for(String dayForecastStr : result) { 
       MainActivityFragment.weather_adapter.add(dayForecastStr); 
      } 
      //also print size of result using logcat to check.     
      //Do notifydata set change here. 
     } 
0

我剛剛遇到了同樣的問題。對我來說有效的方法是在基本URL後立即將密鑰附加到Uri。因此,它應該類似於以下內容,其中key等於openweathermap.org網站上給出的API密鑰,「KEY_PARAM」等於「APPID」。

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 KEY_PARAM = "APPID"; 

     Uri builtUri = Uri.parse(FORECAST_BASE_URL).buildUpon() 
       .appendQueryParameter(KEY_PARAM, key) 
       .appendQueryParameter(QUERY_PARAM, params[0]) 
       .appendQueryParameter(FORMAT_PARAM, format) 
       .appendQueryParameter(UNITS_PARAM, units) 
       .appendQueryParameter(DAYS_PARAM, Integer.toString(numDays)) 
       .build(); 
相關問題