简体   繁体   中英

Android: Attempt to invoke virtual method (onTouch) on a null object reference

I'm trying to set up gesture detection on one of the Linear layouts on a view in my app. The problem is my app crashes whenever I test it with a fling gesture. The error message I receive is the notorious "Attempt to invoke virtual method on a null object reference". I've done research and I understand that the problem stems from trying to call methods on an Activity that is not properly passed into the necessary scope within one's code. That being said, I don't understand how to fix that in my code. Here are the relevant bits of code:

Playfrets.java

public class PlayFrets extends Activity {
    LinearLayout gestureOverlay; 
    GestureListener gestureListener;        
    public void configGestureRecognition(){       //Toolbar gesture recognition
            gestureOverlay = (LinearLayout) findViewById(R.id.toolbarGestureOverlay);
            gestureListener = new GestureListener(PlayFrets.this);
            if (gestureOverlay == null){
                Toast.makeText(PlayFrets.this, "gestureOverlay object is null bro" ,Toast.LENGTH_SHORT).show();
            }
            gestureOverlay.setOnTouchListener(gestureListener);
        }
}

LoadNoteFiles.java

public class LoadNoteFiles extends AsyncTask<Void, Void, Void>{
private Context mContext;
Activity instance;  

public LoadNoteFiles(Context context){ //constructor
    mContext = context;
}

@Override
protected void onPreExecute(){
    PlayFrets.viewSwitch = new ViewSwitcher(mContext);
    PlayFrets.viewSwitch.addView(ViewSwitcher.inflate(mContext, R.layout.splash_screen, null));
    instance = (Activity)mContext;  //cast context from main activity into an activity to access setContentView method
    instance.setContentView(PlayFrets.viewSwitch);
}
...//do in background code omitted
@Override
protected void onPostExecute(Void v){
    PlayFrets.viewSwitch.addView(ViewSwitcher.inflate(mContext, R.layout.activity_play_frets, null));
    PlayFrets.viewSwitch.showNext();
    ((PlayFrets)mContext).configFretboard();
    ((PlayFrets)mContext).configGestureRecognition(); //test gesture recognition
}

GestureListener.java

class GestureListener extends SimpleOnGestureListener implements OnTouchListener {
    Context mContext;
    GestureDetector gDetector;
    static final double SWIPE_MIN_DISTANCE = PlayFrets.getActualHeight()*(0.80);  //must swipe across at least 80% of screen height to register a gesture
    static final int SWIPE_MAX_OFF_PATH = 150;
    static final int SWIPE_THRESHOLD_VELOCITY = 300;

    public GestureListener(Context context) {
        this.mContext = context;
    }

    public GestureListener(Context c, AttributeSet attrs) {
        super();
    }

    public GestureListener(Context context, GestureDetector gDetector) {
        if (gDetector == null){
            gDetector = new GestureDetector(context, this);
        }
        this.mContext = context;
        this.gDetector = gDetector;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {
        //Log.e("gesture", String.valueOf(SWIPE_MIN_DISTANCE));
        if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) {
            if (Math.abs(e1.getX() - e2.getX()) > SWIPE_MAX_OFF_PATH|| Math.abs(velocityY) < SWIPE_THRESHOLD_VELOCITY) {
                return false;
            }
            else if (e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE) {
                //float traveled = e1.getY() - e2.getY();
                //Toast.makeText(context, Float.toString(traveled) + ">" +String.valueOf(SWIPE_MIN_DISTANCE),Toast.LENGTH_SHORT).show();
                Toast.makeText(mContext, "Swiped Up",Toast.LENGTH_SHORT).show();
            } 
            else if (e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE) {
                //float traveled = e2.getY() - e1.getY();
                //Toast.makeText(context, Float.toString(traveled) + ">" +String.valueOf(SWIPE_MIN_DISTANCE),Toast.LENGTH_SHORT).show();
                Toast.makeText(mContext, "Swiped Down",Toast.LENGTH_SHORT).show();
            }
        } 
        return super.onFling(e1, e2, velocityX, velocityY);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return gDetector.onTouchEvent(event);
    }

    public GestureDetector getDetector() {
        return gDetector;
    }

}

Do I need to use a different constructor for GestureListener.java to properly pass in an instance of the activity? What exactly is causing the onTouch() method to be called on a null object? Below is the log detailing the error.

log file

06-15 21:59:46.721: E/InputEventReceiver(6972): Exception dispatching input event.
06-15 21:59:46.721: E/MessageQueue-JNI(6972): Exception in MessageQueue callback: handleReceiveCallback
06-15 21:59:46.741: E/MessageQueue-JNI(6972): java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.view.GestureDetector.onTouchEvent(android.view.MotionEvent)' on a null object reference
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at com.example.guitarsim.GestureListener.onTouch(GestureListener.java:59)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.View.dispatchTouchEvent(View.java:8914)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2673)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2385)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2684)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2346)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2684)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2346)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2684)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2346)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2684)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2346)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2684)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2346)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2552)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1767)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.app.Activity.dispatchTouchEvent(Activity.java:2840)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2513)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.View.dispatchPointerEvent(View.java:9125)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4636)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4474)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4024)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4077)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4043)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4157)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4051)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4214)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4024)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4077)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4043)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4051)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4024)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6485)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6384)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6355)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6575)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.os.MessageQueue.nativePollOnce(Native Method)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.os.MessageQueue.next(MessageQueue.java:143)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.os.Looper.loop(Looper.java:130)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at android.app.ActivityThread.main(ActivityThread.java:5835)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at java.lang.reflect.Method.invoke(Native Method)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at java.lang.reflect.Method.invoke(Method.java:372)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)

Learn to read logcat, it's telling you exactly what the problem is...

06-15 21:59:46.741: E/MessageQueue-JNI(6972): java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.view.GestureDetector.onTouchEvent(android.view.MotionEvent)' on a null object reference
06-15 21:59:46.741: E/MessageQueue-JNI(6972):   at com.example.guitarsim.GestureListener.onTouch(GestureListener.java:59)

The problem is at line 59 of your GestureListener class in the onTouch(...) method...

@Override
public boolean onTouch(View v, MotionEvent event) {
    return gDetector.onTouchEvent(event);
}

Basically your gDetector must be null and there's an attempt to call its onTouchEvent(...) method causing the NPE.

The problem is where you create the instance of the GestureListener in your Activity method configGestureRecognition() as follows...

gestureListener = new GestureListener(PlayFrets.this);

The version of the constructor GestureListener(Context context) doesn't initialise the GestureDetector

Use the constructor which takes a GestureDetector as a parameter...

public GestureListener(Context context, GestureDetector gDetector) {...}

...and either pass in an initialised GestureDetector or null to allow it to create a GestureDetector for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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