Android Wear SensorManager中的潜在缺陷?
我有两个片段,片段A和片段B。片段A使用抖动手势切换到片段B,片段B使用不同的手势切换回片段A。因此,当我在片段A中时,我向SensorManager注册手势A,当检测到抖动时,我取消注册手势A,切换到片段B,并向SensorManager注册手势B 片段A:Android Wear SensorManager中的潜在缺陷?,android,wear-os,android-sensors,Android,Wear Os,Android Sensors,我有两个片段,片段A和片段B。片段A使用抖动手势切换到片段B,片段B使用不同的手势切换回片段A。因此,当我在片段A中时,我向SensorManager注册手势A,当检测到抖动时,我取消注册手势A,切换到片段B,并向SensorManager注册手势B 片段A: public class FragmentA extends Fragment { private MainWearActivity mMainWearActivity; private SensorManager mS
public class FragmentA extends Fragment {
private MainWearActivity mMainWearActivity;
private SensorManager mSensorMgr;
private GestureA gestureA;
private OnShakeListener gestureAListener;
private View view;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMainWearActivity = (MainWearActivity) getActivity();
mSensorMgr = (SensorManager) mMainWearActivity.getSystemService(Activity.SENSOR_SERVICE);
gestureA = new GestureA();
gestureAListener = new OnShakeListener() {
@Override
public void onShake() {
gestureADetected();
}
};
gestureA.setOnShakeListener(gestureAListener);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_a, container, false);
return view;
}
@Override
public void onResume() {
super.onResume();
startListening();
}
@Override
public void onPause() {
stopListening();
super.onPause();
}
private void gestureADetected(){
mMainWearActivity.replaceFragment(mMainWearActivity.getFrag("B"));
}
private void startListening(){
mMainWearActivity.registerListener(gestureA);
}
private void stopListening(){
mMainWearActivity.unregisterListener(gestureA);
}
}
片段B:
public class FragmentB extends Fragment {
private MainWearActivity mMainWearActivity;
private FragmentManager fm;
private SensorManager mSensorMgr;
private GestureB gestureB;
private OnShakeListener gestureBListener;
private View view;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMainWearActivity = (MainWearActivity) getActivity();
fm = mMainWearActivity.getFragmentManager();
mSensorMgr = (SensorManager) mMainWearActivity.getSystemService(Activity.SENSOR_SERVICE);
gestureB = new GestureB();
gestureBListener = new OnShakeListener() {
@Override
public void onShake() {
gestureBDetected();
}
};
gestureB.setOnShakeListener(gestureBListener);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_b, container, false);
return view;
}
@Override
public void onResume() {
super.onResume();
startListening();
}
@Override
public void onPause() {
stopListening();
super.onPause();
}
private void gestureBDetected(){
fm.popBackStackImmediate();
}
private void startListening(){
mMainWearActivity.registerListener(gestureB);
}
private void stopListening(){
mMainWearActivity.unregisterListener(gestureB);
}
}
如果我运行此应用程序,并在片段A和片段B之间连续切换,则SensorManager会在几次之后停止检测手势。在Android手机上,这种设置工作正常,但情况并非如此
这只是我制作的一个小测试应用程序,用于检查行为是否可以复制,但我的实际应用程序要大得多,并且有更多的手势,因此简单地向SensorManager注册所有手势一次并检查不同的片段/手势并不是一个理想的解决方案,因为它变得非常混乱和复杂。是否有人知道如何“清理”SensorManager,使其丢失对任何以前注册/未注册的侦听器的所有引用?或者这只是Android Wear中的一个bug。我用的是Moto360。谢谢。在您最近几天提出的问题中,我没有看到您的事件侦听器/手势检测器的代码发布,这些问题包含类似的代码,我认为它们是相关的。看起来至少有一个使用陀螺传感器。在一个发布的代码版本中,您使用了快速更新率(传感器延迟游戏) 在您的监听/检测过程中是否有逻辑来确保给定的手腕运动只会导致该手势被报告一次?我在考虑设计中的控制流:传感器事件、手势检测、片段事务、监听器注销。因为所有这些都发生在主线程上,并且片段事件是异步的,所以我怀疑在触发手势检测的事件之后,您的侦听器将获得更多的事件。更新速度越快,越有可能出现这种情况。根据我的经验,执行片段事务中涉及的步骤以及片段回调(
onCreateView()
,onResume()
,等等)可能需要20毫秒或更长时间。在调用要删除的片段的onPause()
之前,该片段的侦听器仍然被注册,并且事件正在排队等待侦听器。如果触发多个手势检测,您的片段管理可能会混乱,可能会导致同一片段被多次添加。将Log
语句添加到gestureXDetected()
将确认手势检测一次,正如您的设计所期望的那样
关于
传感器管理器
中的一个bug,您的问题是,什么都有可能,但我认为可能性不大。您可以通过将调试代码放入MainActivity的onCreate()
方法中,在开始正常操作之前,将侦听器注册/注销100次,从而轻松确认您的怀疑,然后观察你的应用程序是否立即变得迟钝,或者在反复切换片段后是否出现延迟。你是否考虑过重构代码以使用状态模式或命令模式,因为你的许多代码似乎是冗余的,而且你的问题可能隐藏得很好,很难追踪?我可能最终不得不使用状态模式,但是,只注册和取消注册侦听器要简单得多。它在安卓手机上运行良好,没有问题。