Reputation: 1288
I have a Fragment Home.java in the MainActivity which has view pager images. I've used a timer to schedule the automatic sliding of the images inside this viewpager. Whenever I click on the back button on the device to exit the application, I get a NULL POINTER EXCEPTION. Here's my code
public class Home extends Fragment {
Timer timer ; //Timer variable
int page = -1; //Page starts at zero.
int page1 = 8; //Number of images there are
int flag = 0;
int y =0;
ImageLoader imageLoader;
DisplayImageOptions options;
//Images to be displayed on top
String[] imageUrls = new String [] {
"https://lh3.googleusercontent.com/-JB9v6rtgHhk/URqup21F-zI/AAAAAAAAAbs/64Fb8qMZWXk/s1024/Golden%252520Grass.jpg",
"https://lh4.googleusercontent.com/-EIBGfnuLtII/URquqVHwaRI/AAAAAAAAAbs/FA4McV2u8VE/s1024/Grand%252520Teton.jpg",
"https://lh4.googleusercontent.com/-WoMxZvmN9nY/URquq1v2AoI/AAAAAAAAAbs/grj5uMhL6NA/s1024/Grass%252520Closeup.jpg",
"https://lh4.googleusercontent.com/-zAvf__52ONk/URqutT_IuxI/AAAAAAAAAbs/D_bcuc0thoU/s1024/Highway%2525201.jpg",
"https://lh4.googleusercontent.com/-vPeekyDjOE0/URquwzJ28qI/AAAAAAAAAbs/qxcyXULsZrg/s1024/Lake%252520Tahoe%252520Colors.jpg",
"https://lh3.googleusercontent.com/-897VXrJB6RE/URquxxxd-5I/AAAAAAAAAbs/j-Cz4T4YvIw/s1024/Leica%25252050mm%252520Summilux.jpg",
"https://lh3.googleusercontent.com/-D_5lNxnDN6g/URqu2Tk7HVI/AAAAAAAAAbs/p0ddca9W__Y/s1024/Lost%252520in%252520a%252520Field.jpg",
"https://lh4.googleusercontent.com/-Z4zGiC5nWdc/URqvBdEwivI/AAAAAAAAAbs/ZRZR1VJ84QA/s1024/Sin%252520Lights.jpg"
};
ViewPager pager;
CirclePageIndicator circleindicator;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.home, container, false);
imageLoader = ImageLoader.getInstance();
imageLoader.init(ImageLoaderConfiguration.createDefault(getActivity()));
options = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.ic_launcher)
.showImageOnFail(R.drawable.add_marker)
.resetViewBeforeLoading(true)
.cacheOnDisc(true)
.imageScaleType(ImageScaleType.EXACTLY)
.bitmapConfig(Bitmap.Config.RGB_565)
.considerExifParams(true)
.displayer(new FadeInBitmapDisplayer(300))
.build();
pager = (ViewPager) rootView.findViewById(R.id.view_pagerhome);
pager.setAdapter(new ImagePagerAdapter(imageUrls));
circleindicator = (CirclePageIndicator) rootView.findViewById(R.id.indicatorhome);
circleindicator.setViewPager(pager);
pageSwitcher(); //This method will change the images automatically after a certain period of time
return rootView;
}
public static Timer getTimerValue()
{
return timer;
}
private void pageSwitcher() {
timer = new Timer(); // At this line a new Thread will be created
timer.scheduleAtFixedRate(new RemindTask(), 0, 3 * 1000);
// Delay in milliseconds
}
// this is an inner class...
class RemindTask extends TimerTask {
//Still to be executed, on manual change page
// Thought!! on pagechangelistener() set the pager.setCurrentItem to current position
//Find a way to determine the current position
//and when you find the current position update page and page1 items accordingly.
public void run() {
// As the TimerTask run on a seprate thread from UI thread we have
// to call runOnUiThread to do work on UI thread.
getActivity().runOnUiThread(new Runnable() {
public void run() {
if(page>8)
{
//This code will execute right to left
//Here page1 is decrement with the starting value of 8 equal to the number of pages
//On Reaching zero it should take the control to the else statement and execute
//left to right
//Managing manual view pager changes
y = pager.getCurrentItem();
y--;
page1 = y;
//managed
pager.setCurrentItem(page1--);
if(page1==-1)
{
page=-1;
flag=0;
}
}
else
{
//This code will execute from left to right.
//where page is the page number (total images - here 8)
//On reaching the end where page = 8, page 1 will set to 8 and then move
//right to left
//Managing manual view pager changes
if(flag==0)
{
int x = pager.getCurrentItem();
page = x;
flag = 1;
}
else
{
int x = pager.getCurrentItem();
x++;
page = x;
}
//managed
pager.setCurrentItem(page++);
if(page==8)
{
page1=8;
}
}
}
});
}
}
//This adapter is for the images on the top of home screen, the sliding images
private class ImagePagerAdapter extends PagerAdapter {
private String[] images;
ImagePagerAdapter(String[] images) {
this.images = images;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public int getCount() {
return images.length;
}
@Override
public Object instantiateItem(ViewGroup view, int position) {
View imageLayout = getLayoutInflater(getArguments()).inflate(R.layout.item_pager_image, view, false);
assert imageLayout != null;
ImageView imageView = (ImageView) imageLayout.findViewById(R.id.image);
final ProgressBar spinner = (ProgressBar) imageLayout.findViewById(R.id.loading);
imageLoader.displayImage(images[position], imageView, options, new SimpleImageLoadingListener() {
@Override
public void onLoadingStarted(String imageUri, View view) {
spinner.setVisibility(View.VISIBLE);
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
spinner.setVisibility(View.GONE);
}
});
view.addView(imageLayout, 0);
return imageLayout;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
@Override
public void restoreState(Parcelable state, ClassLoader loader) {
}
@Override
public Parcelable saveState() {
return null;
}
}
//End of adapter
}
Here's my logcat
How to solve this? What I did was in MainActivity called the timer variable and cancel it before the activity finishes. This is how I did it.
@Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
Timer timer = Home.getTimerValue();
timer.cancel();
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Press Again to Exit", Toast.LENGTH_SHORT).show();
}
If I'm on the MainActivity and I press back twice I don't get a NPE. But if I navigate to another activity and come back to the MainActivity I get this exception again.
Upvotes: 0
Views: 714
Reputation: 10977
You want the timer only to run when the Fragment is active. It is probably still running when you close the app and getActivity()
could return null
at this point. Create and start the Timer
in onStart()
and cancel it in onStop()
of your Fragment. That should work.
Upvotes: 2