【问题标题】:Potential bug in Android Wear SensorManager?Android Wear SensorManager 中的潜在错误?
【发布时间】:2016-02-09 14:08:18
【问题描述】:

我有两个片段,片段 A 和片段 B。片段 A 使用摇晃手势切换到片段 B,片段 B 使用不同的手势切换回片段 A。所以当我在片段 A 中时,我向 SensorManager 注册手势 A,当检测到抖动时,我取消注册手势 A,切换到片段 B,然后向 SensorManager 注册手势 B。

片段 A:

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 注册一次所有手势并检查不同的片段/gestures 不是一个理想的解决方案,因为它变得非常混乱和复杂。有谁知道“清理” SensorManager 以使其丢失对任何以前注册/未注册的侦听器的所有引用的方法?或者这只是 Android Wear 中的一个错误。我使用的设备是 Moto360。谢谢。

【问题讨论】:

  • 您是否考虑过重构代码以使用状态模式或命令模式,因为您的许多代码似乎是多余的,而且您的问题可能被很好地隐藏且难以追踪?
  • 我可能最终不得不使用状态模式,但是,注册和注销监听器会简单得多。它在 Android 手机上运行良好,没有任何问题。

标签: android wear-os android-sensors


【解决方案1】:

在您最近几天的问题中,其中包含类似的代码并且我认为是相关的,我没有看到您的事件侦听器/手势检测器的代码发布。似乎其中至少有一个使用了陀螺仪传感器。在您发布的一个代码版本中,您使用的是快速更新率 (SENSOR_DELAY_GAME)。

您的侦听/检测处理中是否存在逻辑以确保给定的手腕运动仅导致手势被报告一次?我正在考虑您设计中的控制流程:传感器事件、手势检测、片段事务、侦听器注销。因为所有这些都发生在主线程上,并且片段事件是异步的,所以我怀疑您的侦听器会在触发手势检测的事件之后收到更多事件。这更有可能是更新速率更快。根据我的经验,片段事务中涉及的步骤的执行以及片段回调(onCreateView()onResume() 等)可能需要 20 毫秒或更长时间。在调用被删除片段的onPause() 之前,该片段的侦听器仍处于注册状态,并且事件正在排队等待侦听器。如果触发多个手势检测,您的片段管理可能会搞砸,可能会导致多次添加相同的片段。将Log 语句添加到您的gestureXDetected() 将确认手势被检测到一次,正如您的设计所期望的那样。

对于您关于SensorManager 中的错误的问题,好吧,一切皆有可能,但我认为这不太可能。您可以通过在 MainActivity 的 onCreate() 方法中放入调试代码来轻松确认您的怀疑,以便在开始正常操作之前对侦听器进行 100 次注册/取消注册,然后观察您的应用程序是否立即缓慢或在您反复切换片段后出现延迟。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多