简体   繁体   English

Android传感器侦听器未响应,且未在Backstack中添加和删除片段

[英]Android sensor listeners not responding with fragments added and removed from backstack

I have an Android handheld app and an Android wear app that both use fragments and listen for shaking gestures using the sensor manager and custom listeners that I have made. 我有一个Android手持应用程序和一个Android Wear应用程序,它们都使用片段,并使用我制作的传感器管理器和自定义侦听器侦听摇动手势。

On each app I have a main fragment that contains a menu and a sensor manager with my custom listeners registered. 在每个应用程序上,我都有一个主要片段,其中包含一个菜单和一个传感器管理器,其中注册了我的自定义侦听器。 When a user selects a menu item, the main fragment is replaced with the menu item fragment (the menu item fragment has it's own sensor manager with different custom listeners), and when you go back from the menu item fragment, popBackStackImmediate() is called to return to the main fragment. 当用户选择菜单项时,主片段将替换为菜单项片段(菜单项片段具有自己的传感器管理器,具有不同的自定义侦听器),当您从菜单项片段返回时,将调用popBackStackImmediate()返回到主要片段。

This works perfectly on the handheld app, and on the wear app it works fine too, for a while; 这在手持式应用程序上完美运行,在穿戴式应用程序上也可以运行一段时间。 if you open the menu item fragment and then go back to the main fragment continuously, after 5 or 6 times doing this the sensor listeners become sluggish, and eventually stop working. 如果您打开菜单项片段,然后连续返回主片段,则经过5或6次此操作后,传感器侦听器将变慢,并最终停止工作。 Does anyone know what might be causing this? 有谁知道这可能是什么原因?

This is how I handle registering and unregistering the listeners with the sensorManager in each of the fragments: 这是我在每个片段中使用sensorManager处理注册和注销侦听器的方式:

Main Fragment 主要片段

public class MainFragment extends Fragment {

    private MainWearActivity mMainWearActivity;
    View view;

    private SensorManager mSensorMgr;
    private ShakeListener shakeListener;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mMainWearActivity = (MainWearActivity) getActivity();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.fragment_main, container, false);

        mSensorMgr = (SensorManager) mMainWearActivity.getSystemService(Activity.SENSOR_SERVICE);
        shakeListener = new ShakeListener();

        shakeListener.setOnShakeListener(new OnShakeListener() {
            @Override
            public void onShake() {
                    MenuItemFragment mif = new MenuItemFragment();
                    mMainWearActivity.replaceFragment(mif, "menuFrag");
                }
            }
        });

        startListening();
        return view;
    }

    @Override
    public void onPause() {
        stopListening();
        super.onPause();
    }

    @Override
    public void onResume() {
        super.onResume();
        startListening();
    }

    @Override
    public void onDestroyView() {
        stopListening();
        super.onDestroyView();
    }


    private void startListening(){
        mSensorMgr.registerListener(shakeListener, mSensorMgr.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_GAME);
    }

    private void stopListening(){
        mSensorMgr.unregisterListener(shakeListener);
    }
}

Menu Item Fragment 菜单项片段

public class MenuItemFragment extends Fragment {

    private View view;
    private MainWearActivity mMainWearActivity;
    private SensorManager mSensorMgr;
    private FragmentManager fManager;
    private ShakeListener shakeListener;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mMainWearActivity = (MainWearActivity) getActivity();
        fManager = getFragmentManager();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.fragment_menu_item, container, false);

        mSensorMgr = (SensorManager) mMainWearActivity.getSystemService(Activity.SENSOR_SERVICE);
        shakeListener = new ShakeListener();

        shakeListener.setOnShakeListener(new OnShakeListener() {
            @Override
            public void onShake() {
                fManager.popBackStackImmediate();
            }
        });

        startListening();
        return view;
    }

    @Override
    public void onPause() {
        stopListening();
        super.onPause();
    }

    @Override
    public void onResume() {
        super.onResume();
        startListening();
    }

    @Override
    public void onDestroyView() {
        stopListening();
        super.onDestroyView();
    }

    private void startListening(){
        mSensorMgr.registerListener(shakeListener, mSensorMgr.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_GAME);
    }

    private void stopListening(){
        mSensorMgr.unregisterListener(shakeListener);
    }
}

Method to Replace Fragment 片段替换方法

public void replaceFragment(Fragment frag, String fragTag) {
    mFragmentTransaction = mFragmentManager.beginTransaction();
    mFragmentTransaction.replace(R.id.fragmentContainer, frag, fragTag);
    mFragmentTransaction.addToBackStack(null);
    mFragmentTransaction.commit();
}

Like I say, this set up works fine on the handheld app, but on the watch the sensor listener malfunctions after loading and going back from the menu item fragment. 就像我说的那样,此设置在手持式应用程序上可以正常工作,但在手表上,加载并从菜单项片段中返回后,传感器侦听器会发生故障。 Any help would be greatly appreciated, thanks. 任何帮助将不胜感激,谢谢。

EDIT 编辑

So as per the suggestions, I have moved my fragments to the MainActivity class so that they can be re-used. 因此,按照建议,我已将片段移至MainActivity类,以便可以重复使用它们。 I have also changed the replaceFragment method to this instead: 我也将replaceFragment方法改为了:

public void replaceFragment(Fragment frag, String fragTag) {
    Fragment currentFrag = mFragmentManager.findFragmentById(R.id.fragmentContainer);
    mFragmentManager.beginTransaction()
            .remove(currentFrag)
            .add(R.id.fragmentContainer, frag, fragTag)
            .addToBackStack(null)
            .commit();
}

I have placed Logs in the onResume() and onPause() methods of the MainFragment and the MenuItemFragments to check whether they are being called and can confirm that they are. 我将Logs放在MainFragment和MenuItemFragments的onResume()和onPause()方法中,以检查是否正在调用它们并可以确认它们是否被调用。

I have also moved the SensorManager to the MainActivity and use that to register/unregister listeners, which themselves have been moved to the OnCreate() method of each fragment so that new listeners are not being created every time the view is created. 我还将SensorManager移至MainActivity,并使用它来注册/注销侦听器,侦听器本身已移至每个片段的OnCreate()方法,以便在每次创建视图时都不会创建新的侦听器。

After all this the same problem persists. 毕竟,相同的问题仍然存在。 I can go into a MenuItemFragment and back to the MainFragment maybe 8-10 times before the listeners/sensors stop working. 在侦听器/传感器停止工作之前,我可以进入MenuItemFragment并返回MainFragment大约8-10次。 I have also looked at the memory tab of AndroidMonitor in Android Studio as I am going into and out of the fragments, and it appears to fill up steadily until the allocated amount reaches about 5MB before the sensors crash. 当我进入和移出片段时,我还查看了Android Studio中AndroidMonitor的内存选项卡,它似乎稳定地填充,直到分配的内存量达到5MB为止,然后传感器崩溃。

My testing indicates that onResume() and onPause() don't get called by FragmentTransaction.replace() , so it wouldn't surprise me if they also don't get called when that transaction is popped off the back stack. 我的测试表明, FragmentTransaction.replace()不会调用onResume()onPause() ,因此,当该事务从后端堆栈中弹出时,如果它们也未被调用,也不会令我感到惊讶。 You can confirm this in your own code by adding some logging to your onResume() and onPause() methods and watching when they get called. 您可以通过在onResume()onPause()方法中添加一些日志记录并观察它们何时被调用来在自己的代码中进行确认。

If this is indeed the case, the workaround I've used is to call FragmentTransaction.remove() and add() instead of replace() . 如果确实如此,我使用的解决方法是调用FragmentTransaction.remove()add()而不是replace() So your replaceFragment method body would then look like this: 因此,您的replaceFragment方法主体将如下所示:

Fragment currentFrag = fragMgr.findFragmentById(R.id.fragmentContainer);
mFragmentManager.beginTransaction()
    .remove(currentFrag)
    .add(R.id.fragmentContainer, frag, fragTag)
    .addToBackStack(null)
    .commit();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM