android片段内的计时器中的空指针异常

时间:2014-04-04 17:21:00

标签: android android-fragments timer runnable ui-thread

我在MainActivity中有一个Fragment Home.java,它有查看寻呼机图像。我已经使用计时器来安排在此viewpager中自动滑动图像。每当我点击设备上的后退按钮退出应用程序时,我都会得到一个NULL指针异常。这是我的代码

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


}

这是我的logcat

Logcat

如何解决这个问题? 我在MainActivity中所做的是调用timer变量并在活动结束前取消它。这就是我做到的。

 @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();


   }

如果我在MainActivity上,我再按两次,我就没有NPE。但是,如果我导航到另一个活动并返回到MainActivity,我会再次获得此异常。

1 个答案:

答案 0 :(得分:2)

您希望计时器仅在片段处于活动状态时运行。关闭应用时,它可能仍在运行,getActivity()此时可能会返回null。在Timer中创建并启动onStart(),然后在片段onStop()中取消它。这应该有用。