2016-09-29 38 views
0

我正在Android Studio上运行应用程序,同时向arrayadapter对象添加字符串值,我得到空指针异常。我确切的相关代码:Arrayadapter添加方法不接受字符串值

protected void onPostExecute(String[] result) { 

       List<String> wordList = new ArrayList<>(); 
       wordList = Arrays.asList(result); 
       if(wordList!= null) 
       { 
        for(String forecast: wordList) 
        { 
         Log.v(LOG_TAG,"forecast value: "+forecast); 
         mForecastAdapter.add(forecast); 
        } 
        // mForecastAdapter.addAll(wordList); 

       } 
       Log.v(LOG_TAG,"Sorry!! Result is null"); 

      } 

addAll()方法尝试为好,但我需要升级到API 11.所以这是不是一种选择。对于信息:这个结果变量不是空的,在日志中,我每次执行这组代码时都会得到正确的预测值。 我得到的例外是: 显示java.lang.NullPointerException:尝试在空对象引用

这里是我的代码中调用虚拟方法无效android.widget.ArrayAdapter.add(java.lang.Object中)“:

package com.example.khatri.sunshine.app; 

import android.net.Uri; 
import android.os.AsyncTask; 
import android.os.Bundle; 
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.ArrayAdapter; 
import android.widget.ListView; 
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; 
import java.util.Arrays; 
import java.util.List; 
public class ForecastFragment extends Fragment { 
    String[] resultfinal = new String[100]; 
    public ForecastFragment() { 
    } 
    ArrayAdapter<String> mForecastAdapter; 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
       // Add this line in order for this fragment to handle menu events. 
     setHasOptionsMenu(true); 
    } 

    @Override 
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 
     inflater.inflate(R.menu.forecastfragment, menu); 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 

     int id = item.getItemId(); 
     if (id == R.id.action_refresh) { 

      FetchWeatherTask fetchWeatherTask = new FetchWeatherTask(); 
        fetchWeatherTask.execute("94043"); 
     } 
     return super.onOptionsItemSelected(item); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 

     View rootView = inflater.inflate(R.layout.fragment_main, container, false); 
     List<String> weekForecast = new ArrayList<String>(); 
     weekForecast.add("Today-Sunny-88/63"); 
     weekForecast.add("Tomorrow FOggy 77/46"); 
     weekForecast.add("Day after sunny again 45/34"); 
     weekForecast.add("Thur-foggy again 65/34"); 
     weekForecast.add("Fri afternoon rainy 76/32"); 
     weekForecast.add("Sat happy sat 65/12"); 
     weekForecast.add("Day after sunny again 45/34"); 
     weekForecast.add("Thur-foggy again 65/34"); 
     weekForecast.add("Fri afternoon rainy 76/32"); 
     weekForecast.add("Sat happy sat 65/12"); 

     ArrayAdapter<String> mForecastAdapter = new ArrayAdapter<String>(
     getContext(), 
     R.layout.list_item_forecast, 
     R.id.list_item_forecast_textview, 
     weekForecast); 

     ListView listView = (ListView) rootView.findViewById(R.id.listview_forecast); 
     listView.setAdapter(mForecastAdapter); 


     return rootView; 

    } 

    public class FetchWeatherTask extends AsyncTask<String, Void, String[]> { 
     private final String LOG_TAG = FetchWeatherTask.class.getSimpleName(); 

     protected String[] doInBackground(String... params) { 

      HttpURLConnection urlConnection = null; 
      BufferedReader reader = null; 

// Will contain the raw JSON response as a string. 
      String forecastJsonStr = null; 

      String format = "json"; 
      String units = "metric"; 
      int numDays = 7; 
      String appid = "c70ffaa8bf3c10556dc3e82d72d23677"; 

      try { 

       final String FORECAST_BASE_URL = "http://api.openweathermap.org/data/2.5/forecast/daily?"; 
       final String FORMAT_PARAM = "mode"; 
       final String QUERY_PARAM = "q"; 
       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, appid) 
         .build(); 

       URL url = new URL(builtUri.toString()); 

       Log.v(LOG_TAG, "Built URI " + builtUri.toString()); 

       // 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. 
        forecastJsonStr = null; 
       } 
       reader = new BufferedReader(new InputStreamReader(inputStream)); 

       String line; 
       while ((line = reader.readLine()) != null) { 

        buffer.append(line + "\n"); 
       } 

       if (buffer.length() == 0) { 
        // Stream was empty. No point in parsing. 
        forecastJsonStr = null; 
       } 
       forecastJsonStr = buffer.toString(); 

       Log.v(LOG_TAG, "forecast JSON string: " + forecastJsonStr); 
      } catch (Exception e) { 
       Log.e("PlaceholderFragment", "Error ", e); 

       forecastJsonStr = null; 
      } finally { 
       if (urlConnection != null) { 
        urlConnection.disconnect(); 
       } 
       if (reader != null) { 
        try { 
         resultfinal = getWeatherDataFromJson(forecastJsonStr, numDays); 
         reader.close(); 
        } catch (final IOException e) { 
         Log.e("PlaceholderFragment", "Error closing stream", e); 
        } 
        catch (JSONException jsonexception) 
        { 
         Log.e(LOG_TAG,"JSON Exception",jsonexception); 
        } 
       } 
      } 
      return resultfinal; 
     } 



     private String getReadableDateString(long time) { 
      SimpleDateFormat shortenedDateFormat = new SimpleDateFormat("EEE MMM dd"); 
      return shortenedDateFormat.format(time); 
     } 

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


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


      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++) { 
       // 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); 

       // The date/time is returned as a long. We need to convert that 
       // into something human-readable, since most people won't read "1400356800" as 
       // "this saturday". 
       long dateTime; 
       // Cheating to convert this to UTC time, which is what we want anyhow 
       dateTime = dayTime.setJulianDay(julianStartDay+i); 
       day = getReadableDateString(dateTime); 

       // 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(LOG_TAG, "Forecast entry: " + s); 
      } 
      //onPostExecute(resultStrs); 

      return resultStrs; 



     } 

     @Override 
     protected void onPostExecute(String[] result) { 

      List<String> wordList = new ArrayList<>(); 
        wordList = Arrays.asList(result); 
      if(wordList!= null) 
      { 

       // mForecastAdapter.add(result.toString()); 
       for(String forecast: wordList) 
       { 
        Log.v(LOG_TAG,"forecast value: "+forecast); 
        mForecastAdapter.add(forecast); 
       } 
       // mForecastAdapter.addAll(wordList); 

      } 
      Log.v(LOG_TAG,"Sorry!! Reuslt is null"); 

     } 


    } 


} 
+0

你初始化了你的mForecastAdapter变量吗?你可以在这里输入完整的代码 –

+2

因为你没有初始化ArrayAdapter并尝试添加值,请首先初始化你的arrayAdapter,然后添加值 – Shailesh

+0

你检查了你的单词表是否为空?你可以在wordList上添加一个大小条件,然后再试一次吗? –

回答

0

当你采用全局变量,那么你只是第一次初始化,你在整个班级中使用。我希望这会帮助你,并且你得到了你的解决方案。

public class ForecastFragment extends Fragment { 

     ArrayAdapter<String> mForecastAdapter; 


     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { 

     ...... 
     mForecastAdapter = new ArrayAdapter<String>(
          getContext(), 
          R.layout.list_item_forecast, 
          R.id.list_item_forecast_textview, 
          weekForecast); 

     .....  
     } 
    } 
+0

感谢Shailesh,现在纠正它。还有一个疑问,如果你能帮助我。 现在,当我在我的onPostExecute()方法中设置listview.setAdapter(mforecastAdapter)时,它不会在仿真器屏幕上显示。 我将ListView listview设置为全局,并在onCreateView()中初始化它,并试图在onPostExecute()中设置值。 任何想法为什么会发生这种情况? – Anonymous

+0

是的,这是我的乐意帮助你,你的意思是在设备上工作,但模拟器的问题是吗? – Shailesh

0

您初始化中oncreateView)局部mForecastAdapter变量(和提升价值,以全球mForecastAdapter未初始化。这就是为什么它给你空指针。

+0

谢谢Sumeet,这是一个小小的错误。现在纠正它。 – Anonymous

+0

现在,当我在我的onPostExecute()方法中设置listview.setAdapter(mforecastAdapter)时,它不会在仿真器屏幕上显示。 我将ListView listview设置为全局,并在onCreateView()中初始化它,并试图在onPostExecute()中设置值。 任何想法为什么会发生这种情况? – Anonymous

0

重点是片段的生命周期。 在调用onOptionsItemSelected()方法之前,能否确保调用onCreteView()方法?

我建议你添加一些日志代码或设置一些breadpoints看看哪个方法被首先调用。

+0

它只是onCreateView()方法,因为它首先被调用。 – Anonymous

+0

我得到的答复为这一个.... 明确一个ArrayAdapter,mforecastAdapter.clear(),然后, 值添加到该适配器,然后 mForecastAdapter.notifyDataSetChanged(); 这描绘了我的列表视图中的变化:) – Anonymous

0

我从另一个线程这个答案:

明确一个ArrayAdapter,mforecastAdapter.clear(),然后, 值添加到该适配器,然后 mForecastAdapter.notifyDataSetChanged();

这描述了我的列表视图中的变化:)