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

Using RunOnUIThread causing null pointer Exception After Switching to another Fragment

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);
            }
        });
    }
}

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

错误

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

您的 TimerTask 在删除片段后被触发。在这种情况下,getActivity() 将 return 为 null,因此是异常。

我可以建议两个选择:

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

首先,你应该了解Android中的线程。在 Android 中,我们有一个名为 MainUIThread 的线程。我不确定这是不是主线程。但是,它有一个 Looper class.

的实例

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

您的错误消息 java.lang.NullPointerException 表示 getActivity() 方法的 return 值为 null。一个好的起点是 JavaDocs。他们涵盖了这个:

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

  • 调用空对象的实例方法。
  • 正在访问或修改空对象的字段。
  • 将 null 的长度当作一个数组来计算。
  • 像访问数组一样访问或修改 null 的槽。
  • 像抛出值一样抛出 null。

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

适合您的解决方案:

  1. 让我们检查并确保您没有完成 Activity。 (另一种情况是你分离了这个叫做Activity的片段。因为你使用的是ViewPager,我猜你是向左或向右滑动两次。默认情况下它会自动分离你的片段)尝试放弃它。
  2. 如果您必须完成包含您的片段的 Activity 或必须分离您的片段。最简单的方法是在调用 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);
                        }
                    }
                });
            }
        }
    }