2016-02-09 52 views
0

我有兩個片段,片段A和片段B.片段A使用搖動手勢切換到片段B和片段B使用不同的手勢來切換回片段A.因此,當我在片段A的時候,我註冊手勢A與SensorManager配合使用,當檢測到晃動時,我取消註冊手勢A,切換到片段B,並向SensorManager註冊手勢B.Android Wear SensorManager中的潛在錯誤?

片段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註冊的所有手勢一次,檢查不同碎片/手勢不是理想的解決方案,因爲它變得非常混亂和複雜。有誰知道「清理」SensorManager的方法,以便它丟失對之前註冊/未註冊的偵聽器的所有引用?或者這只是Android Wear中的一個錯誤。我使用的設備是Moto360。謝謝。

+0

你有沒有考慮重構代碼以使用狀態模式或命令模式,因爲很多你的代碼似乎是多餘的,你的問題可以很好地隱藏起來,苦苦追尋? –

+0

我可能最終不得不使用狀態模式,但是,只要註冊和註銷監聽器就簡單多了。它在Android手機上正常工作沒有問題。 – Highway62

回答

0

在你最近幾天的問題,其中包含類似的代碼,我推測是相關的,我還沒有看到代碼的發佈你的事件監聽器/手勢探測器。看起來至少有一個使用了陀螺儀傳感器。在您的代碼發佈版本中,您使用的是更新速率(SENSOR_DELAY_GAME)。

是否有邏輯在您的聽音/檢測處理,以確保給定的手腕運動只會使手勢進行一次報告?我正在考慮設計中的控制流程:傳感器事件,手勢檢測,片段事務,偵聽器取消註冊。因爲所有這些都發生在主線程上,並且片段事件是異步的,所以我懷疑您的偵聽器會在觸發手勢檢測之後獲得更多事件。更快的更新率更有可能。根據我的經驗,所涉及的片段交易步驟的執行,與片段回調(onCreateView()onResume()等),以及可以採取20毫秒以上。直到onPause()被調用的片段被調用,該片段的偵聽器仍然被註冊,事件正在爲偵聽器排隊。如果觸發多個手勢檢測,您的片段管理可能會混亂,可能會導致多次添加相同的片段。按照您的設計要求,將Log語句添加到您的gestureXDetected()將確認手勢只被檢測一次。

您關於在SensorManager一個錯誤的問題,那麼,任何事情都是可能的,但我認爲這是不太可能。在開始正常操作之前,通過將調試代碼放入MainActivity的onCreate()方法中,將調試代碼註冊/取消註冊監聽器100次,然後觀察您的應用是否立即停滯或在您重複切換片段後會出現延遲,從而可以輕鬆確認您的懷疑。