2

I am trying to execute some code in my fragment when the back button has been touched. I create an interface in my activity and implement it in my fragment. But when i touch back, it crashes. What is wrong with the way i have done it?

import android.support.v7.app.ActionBarActivity;

public class myActionBarActivity extends ActionBarActivity{
    public OnBackPressedListener onBackPressedListener;

    @Override
    public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.actionbaractivity_layout); //loads fragment

    @Override
    public void onBackPressed(){        
        onBackPressedListener.onActivityBackPressed();

    }

    public interface OnBackPressedListener{
        public void onActivityBackPressed();    
    }   

}

Fragment :

import android.support.v4.app.Fragment;
public class myFragment extends Fragment implements myActionBarActivity.OnBackPressedListener{
    ...
    ...

    @Override
    public void onActivityBackPressed() {
        Toast.makeText(getActivity(), "Back pressed", Toast.LENGTH_SHORT).show();

    }

}

Logcat :

06-21 18:04:30.351: E/InputEventSender(6530): Exception dispatching finished signal.
06-21 18:04:30.351: E/MessageQueue-JNI(6530): Exception in MessageQueue callback: handleReceiveCallback
06-21 18:04:30.351: E/MessageQueue-JNI(6530): java.lang.NullPointerException
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at mypackage.myActionBarActivity.onBackPressed(myActionBarActivity.java:23)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.app.Activity.onKeyUp(Activity.java:2222)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.KeyEvent.dispatch(KeyEvent.java:2917)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.app.Activity.dispatchKeyEvent(Activity.java:2456)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.support.v7.app.ActionBarActivityDelegateICS$WindowCallbackWrapper.dispatchKeyEvent(ActionBarActivityDelegateICS.java:258)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2211)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4583)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4559)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4157)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4214)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4183)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4268)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4191)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4325)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4157)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4214)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4183)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4191)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4157)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4214)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4183)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4301)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:4451)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2223)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1895)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1886)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2200)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.os.MessageQueue.nativePollOnce(Native Method)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.os.MessageQueue.next(MessageQueue.java:132)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.os.Looper.loop(Looper.java:124)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at android.app.ActivityThread.main(ActivityThread.java:5493)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at java.lang.reflect.Method.invokeNative(Native Method)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at java.lang.reflect.Method.invoke(Method.java:525)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1209)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1025)
06-21 18:04:30.351: E/MessageQueue-JNI(6530):   at dalvik.system.NativeStart.main(Native Method)

The right way to do it has been explained here https://stackoverflow.com/a/19133522/2105986. But i could not really understand. I am looking for a simpler way to get it working.

Philipp Jahoda
  • 50,880
  • 24
  • 180
  • 187
faizal
  • 3,497
  • 7
  • 37
  • 62
  • 1
    You have to set your listener, because it is currently always `null`. Follow the steps from the guide from 5. – WonderCsabo Jun 21 '14 at 12:45
  • @Narayansoni thanks but i would rather not force my fragments to implement the interface. So giving the fragment the option to "set" the listener is a more flexible option. – faizal Jun 21 '14 at 13:00
  • can please let me know why have write your back pressed code in fragment ? i think it's better to do in activity. – Haresh Chhelana Jun 21 '14 at 13:17
  • @Haresh my fragment uses the `SearchView` widget in the `ActionBar`. When the `SearchView` is not collapsed, i want the back press to collapse it instead of exiting the fragment. Since all the `SearchView` code is in my fragment, not the activity, I prefer to handle the back press in the fragment itself. I guess i could have done it in the activity as well, but didn't really explore it. – faizal Jun 21 '14 at 13:25

2 Answers2

4

Your application crashes because your Listener object (onBackPressListener) is null.

Somewhere in your code, you need to set the Fragment that implements the OnBackPressListener interface as the Listener.

Example, the Fragment:

public class MyFragment extends Fragment implements OnBackPressListener {
    //...
}

The Activity:

public class MyActivity extends Activity {

    private OnBackPressListener mListener;

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        // assuming the fragment is defined in xml and has the id "myfrag"
        setContentView(R.layout.actionbaractivity_layout); 

        MyFragment f = (MyFragment) getFragmentManager().findFragmentById(R.id.myfrag);
        mListener = f;
    }

    @Override
    public void onBackPressed(){        
        mListener.onActivityBackPressed();   
    }
}

Of course, in that case the Listener is kind of useless since you could simply store the Fragment itself as a member. Alternatively you could provide a setter method for the listener so that it can be set from anywhere.

Philipp Jahoda
  • 50,880
  • 24
  • 180
  • 187
1

Based on comment by @WonderCsabo,

Add this to the activity :

public void setOnBackPressedListener(OnBackPressedListener onBackPressedListener){
        this.onBackPressedListener = onBackPressedListener;
    }

Add this to onResume() in fragment :

((myActionBarActivity)getActivity()).setOnBackPressedListener(this);
faizal
  • 3,497
  • 7
  • 37
  • 62