我正在创建一个应用程序,它在打开时崩溃了。堆栈跟踪提到了为天气代码设置drawable的问题? 这是......
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 :(得分:0)
根据我的理解,下面的方案中可能存在一个问题,
1)检查是否通过在输出中记录服务成功方法获得资源ID。
2)如果您没有收到问题,那么您可以检查您的服务。
3)如果你得到它然后它可能是由弃用的方法引起的,所以如果你得到资源id,请使用下面的方法。
Drawable weatherIconDrawable = ResourcesCompat.getDrawable(getResources(), resourceId, null);
这会对你有帮助。