我有一个简单的天气应用程序,包含一个包含3个片段的视图寻呼机(当前,每小时和每日天气预报)。当我第一次启动我的应用程序时它工作正常,我关闭并打开它。但是,我注意到当我的应用程序已经在后台进程中一段时间然后我打开它时,它会因此异常而崩溃:
java.lang.NullPointerException: Attempt to read from field 'koemdzhiev.com.stormy.weather.Forecast koemdzhiev.com.stormy.ui.MainActivity.mForecast' on a null object reference
at koemdzhiev.com.stormy.ui.Current_forecast_fragment.updateDisplay(Current_forecast_fragment.java:120)
at koemdzhiev.com.stormy.ui.MainActivity$3$3.run(MainActivity.java:234)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5294)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
我怀疑这个异常与我没有使用saveInstance方法保存数据这一事实有关。 这是我目前的片段代码:
public class Current_forecast_fragment extends Fragment {
private static final String TAG = "MainActivity";
private MainActivity mActivity;
TextView mTimeLabel;
TextView mTemperatureLabel;
TextView mHumidityValue;
TextView mPrecipValue;
TextView mSummaryLabel;
TextView mLocationLabel;
TextView mWindSpeedValue;
TextView mFeelsLike;
ImageView mIconImageView;
ImageView mDegreeImageView;
public SwipeRefreshLayout mSwipeRefreshLayout;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity = ((MainActivity) getActivity());
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.current_forefast_fragment, container, false);
mTimeLabel = (TextView)v.findViewById(R.id.timeLabel);
mTemperatureLabel = (TextView)v.findViewById(R.id.temperatureLabel);
mHumidityValue = (TextView)v.findViewById(R.id.humidityValue);
mPrecipValue = (TextView)v.findViewById(R.id.precipValue);
mSummaryLabel = (TextView)v.findViewById(R.id.summaryLabel);
mLocationLabel = (TextView)v.findViewById(R.id.locationLabel);
mWindSpeedValue = (TextView)v.findViewById(R.id.windSpeedValue);
mFeelsLike = (TextView)v.findViewById(R.id.feels_like_label);
mIconImageView = (ImageView)v.findViewById(R.id.iconImageView);
mDegreeImageView = (ImageView)v.findViewById(R.id.degreeImageView);
mSwipeRefreshLayout = (SwipeRefreshLayout)v.findViewById(R.id.current_swipe_refresh_layout);
mSwipeRefreshLayout.setColorSchemeResources(R.color.orange, R.color.blue, R.color.green);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
Log.d("TAG", "Swiping in current!");
//if there is internet and if the mSwipeRefreshLayout in the Hourly and daily fragments are not already running...
if (mActivity.isNetworkAvailable()) {
if (!mActivity.mHourly_forecast_fragment.mSwipeRefreshLayout.isRefreshing() && !mActivity.mDaily_forecast_fragment.mSwipeRefreshLayout.isRefreshing()) {
if (mActivity.isLocationServicesEnabled()) {
if (mActivity.latitude != 0.0 && mActivity.longitude != 0.0) {
mActivity.getForecast(mActivity.latitude, mActivity.longitude);
} else {
mActivity.getLocation();
}
}else{
mActivity.alertForNoLocationEnabled();
}
}else{
mSwipeRefreshLayout.setRefreshing(false);
Toast.makeText(mActivity, "currently refreshing...", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(mActivity, "No Internet Connection!", Toast.LENGTH_LONG).show();
mSwipeRefreshLayout.setRefreshing(false);
}
}
});
//Start the swipe refresh layout on start up is internet available
if(mActivity.isNetworkAvailable())
mSwipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
mSwipeRefreshLayout.setRefreshing(true);
Log.d("TAG","running swiping...");
}
});
return v;
}
public void updateDisplay() {
if(mActivity.mForecast != null) {
Current current = mActivity.mForecast.getCurrent();
//setting the current weather details to the ui
mTemperatureLabel.setText(current.getTemperature() + "");
mTimeLabel.setText("At " + current.getFormattedTime() + " it is");
mHumidityValue.setText(current.getHumidity() + "%");
mPrecipValue.setText(current.getPrecipChange() + "%");
mSummaryLabel.setText(current.getSummery());
mWindSpeedValue.setText(current.getWindSpeed() + "");
mFeelsLike.setText("Feels like: " + current.getFeelsLike());
mLocationLabel.setText(mActivity.locationName);
Drawable drawable = ContextCompat.getDrawable(mActivity, current.getIconId());
mIconImageView.setImageDrawable(drawable);
}else{
Toast.makeText(getActivity(),"Could not update data at this time! Please, try again.",Toast.LENGTH_LONG).show();
}
}
}
片段页面适配器代码:
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private Current_forecast_fragment mCurrent_forecast_fragment;
private Hourly_forecast_fragment mHourly_forecast_fragment;
private Daily_forecast_fragment mDaily_forecast_fragment;
CharSequence Titles[]; // This will Store the Titles of the Tabs which are Going to be passed when ViewPagerAdapter is created
int NumbOfTabs; // Store the number of tabs, this will also be passed when the ViewPagerAdapter is created
// Build a Constructor and assign the passed Values to appropriate values in the class
public ViewPagerAdapter(FragmentManager fm,CharSequence mTitles[], int mNumbOfTabsumb,Current_forecast_fragment current_fragment,
Hourly_forecast_fragment hourly_fragment,
Daily_forecast_fragment daily_fragment) {
super(fm);
this.mCurrent_forecast_fragment = current_fragment;
this.mHourly_forecast_fragment = hourly_fragment;
this.mDaily_forecast_fragment = daily_fragment;
this.Titles = mTitles;
this.NumbOfTabs = mNumbOfTabsumb;
}
//This method return the fragment for the every position in the View Pager
@Override
public Fragment getItem(int position) {
if(position == 0) // if the position is 0 we are returning the First tab
{
return this.mCurrent_forecast_fragment;
}
else if (position == 1) // As we are having 2 tabs if the position is now 0 it must be 1 so we are returning second tab
{
return this.mHourly_forecast_fragment;
}else {
return this.mDaily_forecast_fragment;
}
}
// This method return the titles for the Tabs in the Tab Strip
@Override
public CharSequence getPageTitle(int position) {
return Titles[position];
}
// This method return the Number of tabs for the tabs Strip
@Override
public int getCount() {
return NumbOfTabs;
}
}
我的主要活动代码:
public class MainActivity extends AppCompatActivity {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.mCurrent_forecast_fragment = new Current_forecast_fragment();
this.mHourly_forecast_fragment = new Hourly_forecast_fragment();
this.mDaily_forecast_fragment = new Daily_forecast_fragment();
// Creating The ViewPagerAdapter and Passing Fragment Manager, Titles fot the Tabs and Number Of Tabs.
adapter = new ViewPagerAdapter(getSupportFragmentManager(), Titles, Numboftabs, mCurrent_forecast_fragment,
mHourly_forecast_fragment, mDaily_forecast_fragment);
// Assigning ViewPager View and setting the adapter
pager = (ViewPager) findViewById(R.id.pager);
pager.setOffscreenPageLimit(3);
pager.setAdapter(adapter);
// Assiging the Sliding Tab Layout View
tabs = (SlidingTabLayout) findViewById(R.id.tabs);
tabs.setDistributeEvenly(true); // To make the Tabs Fixed set this true, This makes the tabs Space Evenly in Available width
// Setting Custom Color for the Scroll bar indicator of the Tab View
tabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
@Override
public int getIndicatorColor(int position) {
return ContextCompat.getColor(MainActivity.this, R.color.tabsScrollColor);
}
});
// Setting the ViewPager For the SlidingTabsLayout
tabs.setViewPager(pager);
}
我在MainActivity中有这个方法来更新片段中的数据:
public void getForecast(double latitude, double longitude) {
//scedule no response from the server task...
mScheduledFuture = exec.schedule(mNotAbleToGetWeatherDataTask,12, TimeUnit.SECONDS);
Log.d(TAG, "getForecast initiated...");
String API_KEY = "3ed3a1906736c6f6c467606bd1f91e2c";
String forecast = "https://api.forecast.io/forecast/" + API_KEY + "/" + latitude + "," + longitude + "?units=si";
if (isNetworkAvailable()) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(forecast)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
toggleSwipeRefreshLayoutsOff();
}
});
@Override
public void onResponse(Response response) throws IOException {
runOnUiThread(new Runnable() {
@Override
public void run() {
toggleSwipeRefreshLayoutsOff();
}
});
try {
String jsonData = response.body().string();
if (response.isSuccessful()) {
mForecast = parseForecastDetails(jsonData);
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "isSuccessful - run on UNI threth (update display)...");
//THIS LINE BELLOW CAUSES THE NPE...
mCurrent_forecast_fragment.updateDisplay();
mHourly_forecast_fragment.setUpHourlyFragment();
mDaily_forecast_fragment.setUpDailyFragment();
toggleSwipeRefreshLayoutsOff();
//set the isFirstTime to true so that the next refresh wont get location
isFirstTimeLaunchingTheApp = false;
}
});
} else {
alertUserAboutError();
}
} catch (IOException | JSONException e) {
Log.e(TAG, "Exception caught:", e);
}
}
答案 0 :(得分:1)
是因为mActivity
为空。
在onResume()
方法
mActivity = ((MainActivity) getActivity());
喜欢这个
@Override
public void onResume() {
super.onResume();
mActivity = ((MainActivity) getActivity());
}