切换到另一个片段后使用RunOnUIThread导致空指针异常

时间:2018-12-18 02:25:55

标签: android nullpointerexception android-runonuithread

public class ViewPagerTask extends TimerTask {
    @Override
    public void run() {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (viewPager.getCurrentItem() == 0){
                    viewPager.setCurrentItem(1);
                } else if (viewPager.getCurrentItem() == 1){
                    viewPager.setCurrentItem(2);
                } else  viewPager.setCurrentItem(0);
            }
        });
    }
}

我正在使用此代码来更改视图中的图像。但是问题是我在片段中使用它,当我更改片段并且应用程序运行了几秒钟,然后突然弹出空指针错误。现在,我了解的原因是它尝试更改图像,但找不到视图并创建此错误,我不知道该怎么办。请帮助:)

错误

E/AndroidRuntime: FATAL EXCEPTION: Timer-0
Process: com.example.android.indianmetro, PID: 5150
java.lang.NullPointerException: Attempt to invoke virtual method 'void 
android.support.v4.app.FragmentActivity.runOnUiThread(java.lang.Runnable)' 
on a null object reference
    at com.example.android.indianmetro.HomeFragment$ViewPagerTask.run(HomeFragment.java:258)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
E/AbstractTracker: Can't create handler inside thread that has not called 
Looper.prepare()

2 个答案:

答案 0 :(得分:1)

删除片段后,您的TimerTask被解雇。在这种情况下,getActivity()将返回null并因此返回异常。

我可以提出两个选择:

    TimeTask被触发时,
  1. 将getActivity()输出分配给本地变量,检查并使用,如果不为null。
  2. 取消您的TimerTask在onDetach()中。这是推荐的方法。

答案 1 :(得分:1)

首先,您应该了解Android中的线程。在Android中,我们有一个名为MainUIThread的线程。我不确定这不是主线程。但是,它具有Looper类的实例。

默认情况下,您的片段源基本上在MainUIThread上运行。在创建TimerTask的子类时,您正在创建一个新的Runnable以便在另一个线程中运行源代码,对吗?

您的错误消息java.lang.NullPointerException表示getActivity()方法的返回值为null。 JavaDocs是一个很好的起点。他们有以下内容:

在需要对象的情况下应用程序尝试使用null时抛出。这些包括:

  • 调用空对象的实例方法。
  • 访问或修改空对象的字段。
  • 将null的长度视为一个数组。
  • 访问或修改null插槽,就好像它是一个数组一样。
  • 将null视为Throwable值。

应用程序应抛出此类的实例,以指示对null对象的其他非法使用。

为您提供的解决方案:

  1. 请检查并确保您未完成活动。 (另一种情况是您分离此称为Activity的片段。由于您使用的是ViewPager,我猜您是向左或向右滑动两次。默认情况下,它会自动分离您的片段)。尝试放弃它。
  2. 如果您必须完成包含片段的活动或必须分离片段。简便的方法是在调用runOnUiThread()方法之前将其检查为null。

    public class ViewPagerTask extends TimerTask {
        @Override
        public void run() {
            Activity activity = getActivity();
            if (activity != null) {
                activity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (viewPager.getCurrentItem() == 0) {
                            viewPager.setCurrentItem(1);
                        } else if (viewPager.getCurrentItem() == 1) {
                            viewPager.setCurrentItem(2);
                        } else {
                            viewPager.setCurrentItem(0);
                        }
                    }
                });
            }
        }
    }