2014-07-21 61 views
0

我一直在编写此Android应用(Udacity android课程)一段时间,并突然停止工作。它应该显示一周的天气预报,并在单击列表项时显示更多数据。我已经设法创建列表,但创建其他信息的意图和活动时,一切都崩溃了。Android应用停止工作,原因不明

恢复历史记录没有帮助。我试图从头开始重新创建应用程序,但它甚至在显示列表项之前在早期阶段崩溃。

任何人都可以理解这个错误吗?对我来说,似乎我的手机出了问题,因为没有提及我的代码。

这里的错误:

07-22 00:47:55.084 17339-17339/com.linasko.sunshine2 I/Adreno-EGL﹕ <qeglDrvAPI_eglInitialize:320>: EGL 1.4 QUALCOMM Build: I0404c4692afb8623f95c43aeb6d5e13ed4b30ddbDate: 11/06/13 
07-22 00:47:55.124 17339-17339/com.linasko.sunshine2 D/OpenGLRenderer﹕ Enabling debug mode 0 
07-22 00:47:55.194 17339-17355/com.linasko.sunshine2 D/dalvikvm﹕ GC_FOR_ALLOC freed 228K, 2% free 17047K/17304K, paused 28ms, total 28ms 
07-22 00:47:55.404 17339-17355/com.linasko.sunshine2 D/dalvikvm﹕ GC_FOR_ALLOC freed 318K, 2% free 17241K/17588K, paused 9ms, total 9ms 
07-22 00:47:55.434 17339-17339/com.linasko.sunshine2 D/AndroidRuntime﹕ Shutting down VM 
07-22 00:47:55.434 17339-17339/com.linasko.sunshine2 W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x41652ba8) 
07-22 00:47:55.444 17339-17339/com.linasko.sunshine2 E/AndroidRuntime﹕ FATAL EXCEPTION: main 
    Process: com.linasko.sunshine2, PID: 17339 
    java.lang.NullPointerException 
      at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java:394) 
      at android.widget.ArrayAdapter.getView(ArrayAdapter.java:362) 
      at android.widget.AbsListView.obtainView(AbsListView.java:2255) 
      at android.widget.ListView.makeAndAddView(ListView.java:1790) 
      at android.widget.ListView.fillDown(ListView.java:691) 
      at android.widget.ListView.fillSpecific(ListView.java:1349) 
      at android.widget.ListView.layoutChildren(ListView.java:1608) 
      at android.widget.AbsListView.onLayout(AbsListView.java:2087) 
      at android.view.View.layout(View.java:14817) 
      at android.view.ViewGroup.layout(ViewGroup.java:4631) 
      at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) 
      at android.widget.FrameLayout.onLayout(FrameLayout.java:388) 
      at android.view.View.layout(View.java:14817) 
      at android.view.ViewGroup.layout(ViewGroup.java:4631) 
      at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) 
      at android.widget.FrameLayout.onLayout(FrameLayout.java:388) 
      at android.view.View.layout(View.java:14817) 
      at android.view.ViewGroup.layout(ViewGroup.java:4631) 
      at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) 
      at android.widget.FrameLayout.onLayout(FrameLayout.java:388) 
      at android.view.View.layout(View.java:14817) 
      at android.view.ViewGroup.layout(ViewGroup.java:4631) 
      at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) 
      at android.widget.FrameLayout.onLayout(FrameLayout.java:388) 
      at android.view.View.layout(View.java:14817) 
      at android.view.ViewGroup.layout(ViewGroup.java:4631) 
      at com.android.internal.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:374) 
      at android.view.View.layout(View.java:14817) 
      at android.view.ViewGroup.layout(ViewGroup.java:4631) 
      at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) 
      at android.widget.FrameLayout.onLayout(FrameLayout.java:388) 
      at android.view.View.layout(View.java:14817) 
      at android.view.ViewGroup.layout(ViewGroup.java:4631) 
      at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1983) 
      at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1740) 
      at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:996) 
      at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5600) 
      at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761) 
      at android.view.Choreographer.doCallbacks(Choreographer.java:574) 
      at android.view.Choreographer.doFrame(Choreographer.java:544) 
      at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747) 
      at android.os.Handler.handleCallback(Handler.java:733) 
      at android.os.Handler.dispatchMessage(Handler.java:95) 
      at android.os.Looper.loop(Looper.java:136) 
      at android.app.ActivityThread.main(ActivityThread.java:5001) 
      at java.lang.reflect.Method.invokeNative(Native Method) 
      at java.lang.reflect.Method.invoke(Method.java:515) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) 
      at dalvik.system.NativeStart.main(Native Method) 

下面是以前工作的代码的.java文件。

public class MainActivity extends ActionBarActivity { 

    @Override 
    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(); 
     if (id == R.id.action_settings) { 
      return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 

} 

这是第二类。 getWeatherFromJSON函数由讲师给出,可能与错误无关。

public class ForecastFragment extends Fragment { 

    public ArrayAdapter mForecastAdapter; 

    public ForecastFragment() { 
    } 

    final String POST_CODE = "Kaunas"; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setHasOptionsMenu(true); 
    } 

    @Override 
    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); 
    } 

    @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(); 
     if (id == R.id.action_refresh) { 
      new FetchWeatherTask().execute(POST_CODE); 
      return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 

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

     View rootView = inflater.inflate(R.layout.fragment_main, container, false); 

     ArrayList<String> weather_strings = new ArrayList<String>(Arrays.asList(new String[]{"LOL"})); 
     mForecastAdapter = new ArrayAdapter<String>(getActivity(), 
       R.layout.list_item_forecast, R.id.list_item_forecast_textview, 
       weather_strings); 

     new FetchWeatherTask().execute(POST_CODE); 

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

     return rootView; 
    } 

/* The date/time conversion code is going to be moved outside the asynctask later, 
* so for convenience we're breaking it out into its own method now. 
*/ 
    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. 
     Date date = new Date(time * 1000); 
     SimpleDateFormat format = new SimpleDateFormat("E, MMM d"); 
     return format.format(date).toString(); 
    } 

    /** 
    * 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_DATETIME = "dt"; 
     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); 

      // 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 = dayForecast.getLong(OWM_DATETIME); 
      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; 
     } 

     return resultStrs; 
    } 

    public class FetchWeatherTask extends AsyncTask<String, Void, String[]> { 

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

      // These two need to be declared outside the try/catch 
      // so that they can be closed in the finally block. 
      HttpURLConnection urlConnection = null; 
      BufferedReader reader = null; 

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

      try { 
       // Construct the URL for the OpenWeatherMap query 
       // Possible parameters are available at OWM's forecast API page, at 
       // http://openweathermap.org/API#forecast 
       Uri.Builder uriBuilder = new Uri.Builder(); 
       uriBuilder.scheme("http").authority("api.openweathermap.org").appendPath("data") 
         .appendPath("2.5").appendPath("forecast").appendPath("daily") 
         .appendQueryParameter("q", params[0]) 
         .appendQueryParameter("mode", "json") 
         .appendQueryParameter("units", "metric") 
         .appendQueryParameter("cnt", "7"); 
       URL url = new URL(uriBuilder.build().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. 
        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 { 
       return getWeatherDataFromJson(forecastJsonStr, numDays); 
      } catch (JSONException e) { 
       e.printStackTrace(); 
      } 
      return null; 
     } 

     @Override 
     protected void onPostExecute(String[] strs){ 
      if (strs != null){ 
       mForecastAdapter.clear(); 
       for (String day : strs) { 
        mForecastAdapter.add(day); 
       } 
      } 
     } 
    } 
} 
+0

您能否请您展示您的活动布局? – joao2fast4u

+0

我认为错误发生在'listView.setAdapter(mForecastAdapter)''onCreateView';因为'mForecastAdapter = new ArrayAdapter ...'是不正确的。仔细检查一下'R.id.list_item_forecast_textview'实际上是在'R.layout.list_item_forecast'中。不过,我很可能是错的。 – Jakar

回答

0

有什么可怕的事情发生。第一个应用程序和我从头开始重新创建的应用程序在今天早上尝试启动时都开始工作。