2016-07-18 137 views
0

我正在创建一个应用程序,并在开启时崩溃。堆栈跟踪提到了为天气代码设置可绘制的问题? 这...ServiceSuccess方法失败?

Process: com.oxinc.android.drate, PID: 22629 
                    java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageDrawable(android.graphics.drawable.Drawable)' on a null object reference 
                     at com.oxinc.android.drate.MainActivity.serviceSuccess(MainActivity.java:243) 
                     at com.oxinc.android.drate.service.YahooWeatherService$1.onPostExecute(YahooWeatherService.java:93) 
                     at com.oxinc.android.drate.service.YahooWeatherService$1.onPostExecute(YahooWeatherService.java:35) 
                     at android.os.AsyncTask.finish(AsyncTask.java:651) 
                     at android.os.AsyncTask.-wrap1(AsyncTask.java) 
                     at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668) 
                     at android.os.Handler.dispatchMessage(Handler.java:102) 
                     at android.os.Looper.loop(Looper.java:148) 
                     at android.app.ActivityThread.main(ActivityThread.java:5456) 
                     at java.lang.reflect.Method.invoke(Native Method) 
                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) 
                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 

这里是MainActivity.java

package com.oxinc.android.drate; 

import android.app.Activity; 
import android.support.v4.content.ContextCompat; 
import android.support.v7.app.AppCompatActivity; 

import android.support.v7.app.AppCompatActivity; 

import android.Manifest; 
import android.app.ProgressDialog; 
import android.content.Context; 
import android.content.Intent; 
import android.content.SharedPreferences; 
import android.content.pm.PackageManager; 
import android.graphics.drawable.Drawable; 
import android.location.Criteria; 
import android.location.Location; 
import android.location.LocationListener; 
import android.location.LocationManager; 
import android.preference.PreferenceManager; 
import android.support.design.widget.TabLayout; 
import android.support.design.widget.FloatingActionButton; 
import android.support.design.widget.Snackbar; 
import android.support.v4.app.ActivityCompat; 
import android.support.v7.app.AppCompatActivity; 
import android.support.v7.widget.Toolbar; 

import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragmentPagerAdapter; 
import android.support.v4.view.ViewPager; 
import android.os.Bundle; 
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.EditText; 
import android.widget.ImageView; 
import android.widget.TextView; 
import android.widget.Toast; 

import com.oxinc.android.drate.data.Channel; 
import com.oxinc.android.drate.data.Condition; 
import com.oxinc.android.drate.data.LocationResult; 
import com.oxinc.android.drate.fragments.SettingsFragment; 
import com.oxinc.android.drate.listener.GeocodingServiceListener; 
import com.oxinc.android.drate.listener.WeatherServiceListener; 
import com.oxinc.android.drate.service.GoogleMapsGeocodingService; 
import com.oxinc.android.drate.service.WeatherCacheService; 
import com.oxinc.android.drate.service.YahooWeatherService; 


public class MainActivity extends AppCompatActivity implements WeatherServiceListener, GeocodingServiceListener, LocationListener { 

    private ImageView weatherIconImageView; 
    private TextView temperatureTextView; 
    private TextView conditionTextView; 
    private TextView locationTextView; 
    private YahooWeatherService weatherService; 
    private GoogleMapsGeocodingService geocodingService; 
    private WeatherCacheService cacheService; 
    private ProgressDialog dialog; 


//Other Variables 
    private void startSettingsActivity() { 
     Intent intent = new Intent(this, SettingsActivity.class); 
     startActivity(intent); 
    } 


    /** 
    * The {@link android.support.v4.view.PagerAdapter} that will provide 
    * fragments for each of the sections. We use a 
    * {@link FragmentPagerAdapter} derivative, which will keep every 
    * loaded fragment in memory. If this becomes too memory intensive, it 
    * may be best to switch to a 
    * {@link android.support.v4.app.FragmentStatePagerAdapter}. 
    */ 
    private SectionsPagerAdapter mSectionsPagerAdapter; 

    /** 
    * The {@link ViewPager} that will host the section contents. 
    */ 
    private ViewPager mViewPager; 

    //Weather Implemented// 


    // weather service fail flag 
    public boolean weatherServicesHasFailed = false; 

    public SharedPreferences preferences = null; 


    //OnCreate Method 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     weatherIconImageView = (ImageView) findViewById(R.id.weatherIconImageView); 
     temperatureTextView = (TextView) findViewById(R.id.temperatureTextView); 
     conditionTextView = (TextView) findViewById(R.id.conditionTextView); 
     locationTextView = (TextView) findViewById(R.id.locationTextView); 

//  Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
//  setSupportActionBar(toolbar); 
     // Create the adapter that will return a fragment for each of the three 
     // primary sections of the activity. 
     mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); 

     // Set up the ViewPager with the sections adapter. 
     mViewPager = (ViewPager) findViewById(R.id.container); 
     mViewPager.setAdapter(mSectionsPagerAdapter); 

     //Tabbed Layout 
     TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs); 
     tabLayout.setupWithViewPager(mViewPager); 

     //Floating Action Button 
     FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 
     fab.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       startSettingsActivity(); 
      } 
     }); 

     preferences = PreferenceManager.getDefaultSharedPreferences(this); 

     weatherService = new YahooWeatherService(this); 
     weatherService.setTemperatureUnit(preferences.getString(getString(R.string.pref_temperature_unit), null)); 

     geocodingService = new GoogleMapsGeocodingService(this); 
     cacheService = new WeatherCacheService(this); 


     if (preferences.getBoolean(getString(R.string.pref_needs_setup), true)) { 
      startSettingsActivity(); 
     } else { 

      dialog = new ProgressDialog(this); 
      dialog.setMessage(getString(R.string.loading)); 
      dialog.setCancelable(true); 
      dialog.show(); 

      String location = null; 

      if (preferences.getBoolean(getString(R.string.pref_geolocation_enabled), true)) { 
       String locationCache = preferences.getString(getString(R.string.pref_cached_location), null); 

       if (locationCache == null) { 
        getWeatherFromCurrentLocation(); 
       } else { 
        location = locationCache; 
       } 
      } else { 
       location = preferences.getString(getString(R.string.pref_manual_location), null); 
      } 

      if (location != null) { 
       weatherService.refreshWeather(location); 
      } 
     } 

    } 

    private void getWeatherFromCurrentLocation() { 
     // system's LocationManager 
     LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); 

     // medium accuracy for weather, good for 100 - 500 meters 
     Criteria locationCriteria = new Criteria(); 
     locationCriteria.setAccuracy(Criteria.ACCURACY_FINE); 

     String provider = locationManager.getBestProvider(locationCriteria, true); 

     // single location update 
     if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
      // TODO: Consider calling 
      // ActivityCompat#requestPermissions 
      // here to request the missing permissions, and then overriding 
      // public void onRequestPermissionsResult(int requestCode, String[] permissions, 
      //           int[] grantResults) 
      // to handle the case where the user grants the permission. See the documentation 
      // for ActivityCompat#requestPermissions for more details. 
      return; 
     } 
     locationManager.requestSingleUpdate(provider, this, null); 
    } 




    @Override 
    public void serviceSuccess(Channel channel) { 

     dialog.hide(); 

     Condition condition = channel.getItem().getCondition(); 

     int resourceId = getResources().getIdentifier("drawable/icon_" + condition.getCode(), null, getPackageName()); 

     @SuppressWarnings("deprecation") 
     Drawable weatherIconDrawable = getResources().getDrawable(resourceId); 

     weatherIconImageView.setImageDrawable(weatherIconDrawable); 

     String temperatureLabel = getString(R.string.temperature_output, condition.getTemperature(), channel.getUnits().getTemperature()); 

     temperatureTextView.setText(temperatureLabel); 
     conditionTextView.setText(condition.getDescription()); 
     locationTextView.setText(channel.getLocation()); 
    } 

    @Override 
    public void serviceFailure(Exception exception) { 
     // display error if this is the second failure 
     if (weatherServicesHasFailed) { 
      dialog.hide(); 
      Toast.makeText(this, exception.getMessage(), Toast.LENGTH_LONG).show(); 
     } 
     else { 
      // error doing reverse geocoding, load weather data from cache 
      weatherServicesHasFailed = true; 
      // OPTIONAL: let the user know an error has occurred then fallback to the cached data 
      Toast.makeText(this, exception.getMessage(), Toast.LENGTH_SHORT).show(); 

      cacheService.load(this); 
     } 
    } 

    @Override 
    public void geocodeSuccess(LocationResult location) { 
     // completed geo coding successfully 
     weatherService.refreshWeather(location.getAddress()); 

     SharedPreferences.Editor editor = preferences.edit(); 
     editor.putString(getString(R.string.pref_cached_location), location.getAddress()); 
     editor.apply(); 
    } 

    @Override 
    public void geocodeFailure(Exception exception) { 
     // GeoCoding failed, try loading weather data from the cache 
     cacheService.load(this); 
    } 

    @Override 
    public void onLocationChanged(Location location) { 
     geocodingService.refreshLocation(location); 
    } 

    @Override 
    public void onStatusChanged(String s, int i, Bundle bundle) { 
     // OPTIONAL: implement your custom logic here 
    } 

    @Override 
    public void onProviderEnabled(String s) { 
     // OPTIONAL: implement your custom logic here 
    } 

    @Override 
    public void onProviderDisabled(String s) { 
     // OPTIONAL: implement your custom logic here 
    } 

//On Create 

    @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, menu); 
     return true; 
    } 



    /** 
    * A {@link FragmentPagerAdapter} that returns a fragment corresponding to 
    * one of the sections/tabs/pages. 
    */ 
    public class SectionsPagerAdapter extends FragmentPagerAdapter { 

     public SectionsPagerAdapter(FragmentManager fm) { 
      super(fm); 
     } 

     @Override 
     public int getCount() { 
      // Show 3 total pages. 
      return 3; 
     } 

     @Override 
     public CharSequence getPageTitle(int position) { 
      switch (position) { 
       case 0: 
        return "Hydration"; 
       case 1: 
        return "Weigh In"; 
       case 2: 
        return "Weather"; 
      } 
      return null; 
     } 


     @Override 
     public Fragment getItem(int position) { 
      switch (position) { 
       case 0: 
        return new Hydration(); 
       case 1: 
        return new Weight(); 
       case 2: 
        return new Weather(); 
       default: 
        // this should never happen 
        return null; 
       //return new Fragment(); 
      } 
     } 
    } 



     public int quantity = 0; 
     public String outcome = ""; 
     public int required = 0; 
     public int height = 0; 

    public void eight(View view) { 
     quantity = quantity + 8; 
     displayQuantity(quantity); 
    } 

    public void twelve(View view) { 
     quantity = quantity + 12; 
     displayQuantity(quantity); 
    } 

    public void sixteen(View view) { 
     quantity = quantity + 16; 
     displayQuantity(quantity); 
    } 

    public void thirty_two(View view) { 
     quantity = quantity + 32; 
     displayQuantity(quantity); 
    } 

    public void sixty_four(View view) { 
     quantity = quantity + 64; 
     displayQuantity(quantity); 
    } 

    //Reset Button 
    public void reset(View view) { 
     quantity = 0; 
     displayQuantity(quantity); 
     outcome = ""; 
//  displayOutcome(outcome); 
    } 


    /** 
    * This method displays the given quantity value on the screen. 
    */ 
    public void displayQuantity(int quantity) { 
     TextView quantityTextView = (TextView) findViewById(
       R.id.quantity_text_view); 
      quantityTextView.setText(quantity + ""); 
    } 
} 

感谢您的帮助。过去几天我试图自己弄清楚,我不知道ServiceSuccess方法有什么问题。让我知道如果你想/需要看到更多的代码...

新增异步任务YahooWeatherService

package com.oxinc.android.drate.service; 

import android.net.Uri; 
import android.os.AsyncTask; 

import org.json.JSONObject; 

import java.io.BufferedReader; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.net.URL; 
import java.net.URLConnection; 
import com.oxinc.android.drate.data.Channel; 
import com.oxinc.android.drate.listener.WeatherServiceListener; 

public class YahooWeatherService { 
    private WeatherServiceListener listener; 
    private Exception error; 
    private String temperatureUnit = "C"; 

    public YahooWeatherService(WeatherServiceListener listener) { 
     this.listener = listener; 
    } 

    public String getTemperatureUnit() { 
     return temperatureUnit; 
    } 

    public void setTemperatureUnit(String temperatureUnit) { 
     this.temperatureUnit = temperatureUnit; 
    } 

    public void refreshWeather(String location) { 

     new AsyncTask<String, Void, Channel>() { 
      @Override 
      protected Channel doInBackground(String[] locations) { 

       String location = locations[0]; 

       Channel channel = new Channel(); 

       String unit = getTemperatureUnit().equalsIgnoreCase("f") ? "f" : "c"; 

       String YQL = String.format("select * from weather.forecast where woeid in (select woeid from geo.places(1) where text=\"%s\") and u='" + unit + "'", location); 

       String endpoint = String.format("https://query.yahooapis.com/v1/public/yql?q=%s&format=json", Uri.encode(YQL)); 

       try { 
        URL url = new URL(endpoint); 

        URLConnection connection = url.openConnection(); 
        connection.setUseCaches(false); 

        InputStream inputStream = connection.getInputStream(); 

        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); 
        StringBuilder result = new StringBuilder(); 
        String line; 
        while ((line = reader.readLine()) != null) { 
         result.append(line); 
        } 

        JSONObject data = new JSONObject(result.toString()); 

        JSONObject queryResults = data.optJSONObject("query"); 

        int count = queryResults.optInt("count"); 

        if (count == 0) { 
         error = new LocationWeatherException("No weather information found for " + location); 
         return null; 
        } 

        JSONObject channelJSON = queryResults.optJSONObject("results").optJSONObject("channel"); 
        channel.populate(channelJSON); 

        return channel; 

       } catch (Exception e) { 
        error = e; 
       } 

       return null; 
      } 

      @Override 
      protected void onPostExecute(Channel channel) { 

       if (channel == null && error != null) { 
        listener.serviceFailure(error); 
       } else { 
        listener.serviceSuccess(channel); 
       } 

      } 

     }.execute(location); 
    } 

    public class LocationWeatherException extends Exception { 
     public LocationWeatherException(String detailMessage) { 
      super(detailMessage); 
     } 
    } 
} 
+0

看看你发布的LogCat。您的onPostExecute中有一个NullPointerException,但没有发布AsyncTask的代码。您发布的所有代码与您的问题无关。 – greenapps

+0

好的@greenapps我会在稍后发布异步。 –

+0

@greenapps我添加了异步任务。谢谢 –

回答

0

按我的理解,可以有以下情况中的一个问题,

1)检查是否通过将日志记录在输出中获取服务成功方法的资源ID。

2)如果你没有得到那么问题在那里,你可以检查你的服务。

3)如果你正在得到它,那么它可能是由不推荐使用的方法引起的,所以如果你使用下面的方法获得资源ID。

Drawable weatherIconDrawable = ResourcesCompat.getDrawable(getResources(), resourceId, null); 

这会帮助你。

+0

谢谢你,因为我相信它比弃用的方法更好。但是这并没有解决应用程序崩溃的问题。由于问题出在异步任务上,我相信@greenapps有正确的想法。 –