문제

I want to have a sensormanager on a fragment, which is only active when the fragment is active. If the user changes the fragment, the listener should be removed.

Adding and removing the listener is pretty simple. I'm not aware of any listeners / function on the fragment side, when the fragment appears / disappears. Also a problem was, that on almost all functions, this.getActivity() returned a null pointer.

도움이 되었습니까?

해결책 2

Hold a reference of Activity in your fragment to handle that nullpointerexception.

Here is an example of a fragment.

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
    }

}

Debug that code do determine if you should handle the binding there or in another method e.g. onCreate of a fragment. I have not tested this code for your purpose.

Edit: This is indeed as commented below a dirty fix and could easily resolve into exceptions in some cases. I just wanted to show how you can use fragment lifecycle methods to bind and unbind sensors with a reference to activity. I'm currently learning fragments for quite some time but still don't understand them thoroughly. I advice you to take a look at the source of Fragment and other components involved. This is the only place were fragments are documented thoroughly hence the documentation on reference in my opinion isn't that explanatory.

Some of the options regarding null value Activity:

  • If you want to be completely sure that getActivity doesn't return null you should wait for onActivityCreated to be called. This method tells the fragment that its activity has completed its own Activity.onCreate(). After this getActivity() will not return null until initState() gets called by the 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;
    }
    
  • Before you call getActivity you can always check if activity isn't null by calling isAdded() method. As you can see below this method checks if mActivity isn't null. Optionally you can create a recursive function with Handler.postDelayed that tries to return an non null Activity in intervalls (you should add a max try counter). But this is also a dirty trick.

    //Return true if the fragment is currently added to its activity.
    
    final public boolean isAdded() {
        return mActivity != null && mAdded;
    }
    

다른 팁

That's my solution. I tried to cut it out of my Fragment. If there is anything wrong / syntax issues, please let me know.

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);
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top