MAK
MAK

Reputation: 1288

Null Pointer exception in timer inside android fragment

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

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

Answers (1)

SimonSays
SimonSays

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

Related Questions