即使我是常客,这是我在Stackoverflow上的第一个问题,所以请保持温和。 ;)
我有一个可以使用视图寻呼机或操作栏下拉列表横向导航的活动。为了实现这一点,我附加了一个OnPageChangeListener和一个OnNavigationListener来在操作栏导航时更新视图寻呼机,反之亦然。
为了避免无限循环(寻呼机监听器设置操作栏,导航监听器得到通知并设置寻呼机,寻呼机获得通知并设置操作栏等),我获得了一个锁并在我的开始检查事件处理程序(布尔字段inhibited
)。
由于我知道后续更新将异步发生,通过Android在消息队列上发布布局请求,我也会异步释放锁定,将其包装在Runnable
中并将其发布到队列中。
我的期望是,我的runnable被放置在队列之后框架发布的所有消息,以更新操作栏微调器,查看寻呼机以及它认为需要的任何其他内容这样做,因为这些都应该在致电pager.setCurrentItem
,navigationAdapter.notifyDataSetChanged
和setSelectedNavigationItem
时发布。 (期望也会反映在//注释中。)但是,在运行此代码时,我发现在已经释放锁之后,我会从OnNavigationListener调用我的回调。
我的问题是,此延迟通话来自何处以及我如何优雅地阻止它(没有像postDelayed
之类的丑陋黑客)?
以下是我的听众的代码:
private class NavigationListener implements OnPageChangeListener, OnNavigationListener {
private boolean inhibited = false;
protected void inhibit() { inhibited = true; }
protected void release() { inhibited = false; }
private void moveToPosition(int monthId) {
if (!inhibited) {
try {
inhibit();
pager.setCurrentItem(pagerAdapter.getIndex(monthId), true);
navigationAdapter.notifyDataSetChanged();
getActionBar().setSelectedNavigationItem(navigationAdapter.getPositionForMonth(monthId));
} finally {
// Need to release asynchronously because calling setCurrentItem and notifyDataSetChanged will
// (asynchronously) refresh the UI and cause calls to their respective listeners. Therefore, simply
// releasing the lock would result in an infinite loop.
// When posting this runnable, any posts from setting the pager page and refreshing the spinner data
// will already have been posted, so the release call is guaranteed to be behind them in the message queue.
// Likewise, it is sure to be executed before the user can produce more input events, that is, any additional
// swipe gestures or selections will be added to the message queue after the release call.
pager.post(new Runnable() {
@Override
public void run() { release(); }
});
}
}
}
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
int month = (int) itemId;
moveToPosition(month);
/* more irrelevant code here */
return true;
}
public void onPageScrollStateChanged(int arg0) {}
public void onPageScrolled(int arg0, float arg1, int arg2) {}
public void onPageSelected(int position) {
moveToPosition(pagerAdapter.getMonthId(position));
}
}
如果需要可以发布更多代码但不想发送垃圾邮件......