23


我想安排一个动作来自动更改我的 ViewPager 页面。我试过了:

@Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ...

    swipeTimer = new Timer();
    swipeTimer.schedule(new TimerTask() {

         @Override
         public void run() {
            if (currentPage == NUM_PAGES) {
                currentPage = 0;
            }
            featureViewPager.setCurrentItem(currentPage++, true);
         }
    }, 100, 500);

但我总是得到:

E/AndroidRuntime(5381): FATAL EXCEPTION: Timer-0
E/AndroidRuntime(5381): java.lang.IllegalStateException: Must be called from main thread of process

我已经在主线程中了对吧?我该如何解决这个问题?
谢谢你的时间。

编辑:
=====================================


感谢您的所有回答。基于这些回复,我遇到了 2 个解决方案:
解决方案 1:

swipeTimer = new Timer();
            swipeTimer.schedule(new TimerTask() {

                @Override
                public void run() {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            if (currentPage == NUM_PAGES) {
                                currentPage = 0;
                            }
                            featureViewPager.setCurrentItem(currentPage++, true);
                        }
                    });
                }
            }, 500, 3000);

解决方案2:

final Handler handler = new Handler();
                final Runnable Update = new Runnable() {
                    public void run() {
                        if (currentPage == NUM_PAGES) {
                            currentPage = 0;
                        }
                        featureViewPager.setCurrentItem(currentPage++, true);
                    }
                };

            swipeTimer = new Timer();
            swipeTimer.schedule(new TimerTask() {

                @Override
                public void run() {
                    handler.post(Update);
                }
            }, 500, 3000);

哪个更好或者它们是一样的?
再次感谢。

4

4 回答 4

62

如果要在主 UI 中使用线程,则需要使用处理程序来处理它。

Handler handler = new Handler();

        Runnable update = new Runnable()  {

            public void run() {
                if ( currentPage == NUM_PAGES ) {

                    currentPage = 0;
                }
                featureViewPager.setCurrentItem(currentPage++, true);
            }
        };


        new Timer().schedule(new TimerTask() {

            @Override
            public void run() {
                handler.post(update);
            }
        }, 100, 500);
于 2013-06-18T11:41:13.897 回答
10

如何解决它的最简单方法是创建一个 postDelayed 可运行

    private Handler mHandler;
    public static final int DELAY = 5000;

    Runnable mRunnable = new Runnable()
    {

        @Override
        public void run()
        {
            //TODO: do something like mViewPager.setCurrentPage(mIterator);
            mHandler.postDelayed( mRunnable , DELAY );
        }
    };

如您所见,它将无限循环。当你想停止它时,只需调用

        mHandler.removeCallbacks( mRunnable );
于 2013-06-18T11:40:14.380 回答
2

TimerTask 将在它自己的线程上运行(= 不是 UI 线程)。

您可以使用 Handler 直接在主线程上调用 setCurrentItem。

于 2013-06-18T11:36:45.493 回答
0

对于 kotlin 扩展爱好者。这对 viewPage2 自动页面更改很有帮助

fun ViewPager2.enableAutoScroll(totalPages: Int): Timer {
    val autoTimerTask = Timer()
    var currentPageIndex = currentItem
    autoTimerTask.schedule(object : TimerTask() {
        override fun run() {
            currentItem = currentPageIndex++
            if (currentPageIndex == totalPages) currentPageIndex = 0
        }
    }, 0, DELAY_FOUR_SECONDS)

    // Stop auto paging when user touch the view
    getRecyclerView().setOnTouchListener { _, event ->
        if (event.action == MotionEvent.ACTION_DOWN) autoTimerTask.cancel()
        false
    }

    return autoTimerTask // Return the reference for cancel
}

fun ViewPager2.getRecyclerView(): RecyclerView {
    val recyclerViewField = ViewPager2::class.java.getDeclaredField("mRecyclerView")
    recyclerViewField.isAccessible = true
    return recyclerViewField.get(this) as RecyclerView
}
于 2022-01-03T12:02:42.970 回答