1

我想在片段上有一个传感器管理器,它仅在片段处于活动状态时才处于活动状态。如果用户更改片段,则应删除侦听器。

添加和删​​除监听器非常简单。当片段出现/消失时,我不知道片段端的任何侦听器/函数。还有一个问题是,几乎所有函数都this.getActivity()返回一个空指针。

4

2 回答 2

2

这就是我的解决方案。我试图从我的 Fragment 中删除它。如果有任何错误/语法问题,请告诉我。

public class MyFragment extends Fragment implements SensorEventListener {
    private SensorManager mSensorManager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mSensorManager = (SensorManager) this.getActivity().getSystemService(Activity.SENSOR_SERVICE);
    }

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

        return rootView;
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        float x = event.values[0], y = event.values[1];
    }

    @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { }

    @Override
    public void setMenuVisibility(boolean menuVisible) {
        super.setMenuVisibility(menuVisible);

        // First starts (gets called before everything else)
        if(mSensorManager == null) {
            return;
        }

        if(menuVisible) {
            this.registerSensorListener();
        } else {
            this.unregisterSensorListener();
        }   
    }

    @Override
    public void onStart() {
        super.onStart();

        if(this.getUserVisibleHint()) {
            this.registerSensorListener();
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        this.unregisterSensorListener();
    }

    private void registerSensorListener() {
        mSensorManager.registerListener(this, mSensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0), SensorManager.SENSOR_DELAY_FASTEST);
    }

    private void unregisterSensorListener() {
        mSensorManager.unregisterListener(this);
    }
}
于 2013-09-27T14:49:58.563 回答
0

在您的片段中保留 Activity 的引用以处理该空指针异常。

这是一个片段的例子。

public class YourFragment extends Fragment {

    private Activity mActivity;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        mActivity = activity;
    }

    @Override
    public void onResume() {
        super.onResume();
        // BIND sensor here with mActivity, 
        // could also be done in other fragment lifecycle events, 
        // depends on how you handle configChanges

    }

    @Override
    public void onPause() {
        super.onPause();
        // UNBIND sensor here from mActivity, 
        // could also be done in other fragment lifecycle events, 
        // depends on how you handle configChanges
    }

}

调试该代码确实确定您是否应该在此处或以其他方法处理绑定,例如片段的 onCreate。我没有为您的目的测试此代码。

编辑:这确实是一个肮脏的修复下面的评论,在某些情况下可以很容易地解决异常。我只是想展示如何使用片段生命周期方法来绑定和取消绑定传感器以及对活动的引用。我目前正在学习片段很长一段时间,但仍然没有完全理解它们。我建议您查看Fragment的来源和其他相关组件。这是唯一完整记录片段的地方,因此我认为参考文档不是那么解释性的。

关于空值活动的一些选项:

  • 如果您想完全确定 getActivity 不返回 null 您应该等待onActivityCreated被调用。这个方法告诉fragment它的activity已经完成了它自己的Activity.onCreate()。在此之后 getActivity() 将不会返回 null,直到 initState() 被 FragmentManager 调用。

     // Called by the fragment manager once this fragment has been removed,
     // so that we don't have any left-over state if the application decides
     // to re-use the instance.  This only clears state that the framework
     // internally manages, not things the application sets.
    
    void initState() {
        mIndex = -1;
        mWho = null;
        mAdded = false;
        mRemoving = false;
        mResumed = false;
        mFromLayout = false;
        mInLayout = false;
        mRestored = false;
        mBackStackNesting = 0;
        mFragmentManager = null;
        mActivity = null;
        mFragmentId = 0;
        mContainerId = 0;
        mTag = null;
        mHidden = false;
        mDetached = false;
        mRetaining = false;
        mLoaderManager = null;
        mLoadersStarted = false;
        mCheckedForLoaderManager = false;
    }
    
  • 在调用 getActivity 之前,您始终可以通过调用 isAdded() 方法检查活动是否不为空。正如您在下面看到的,此方法检查 mActivity 是否不为空。或者,您可以使用 Handler.postDelayed 创建一个递归函数,该函数尝试在间隔中返回一个非空活动(您应该添加一个最大尝试计数器)。但这也是一个肮脏的伎俩。

    //Return true if the fragment is currently added to its activity.
    
    final public boolean isAdded() {
        return mActivity != null && mAdded;
    }
    
于 2013-09-27T11:25:06.377 回答