Search code examples
androidviewandroid-activitybroadcastreceiverfragment

Access an Activity from a Fragment plugged into another Activity


I have been using this example as a base for my project.

I have changed the project to use an ArrayAdapter for the titles-fragment's ListItems and changed the DetailsFragment's View to display a custom layout, which as a Button that is supposed to add an entry into a database.

Instead of generating widgets like in the example, I just inflate a custom XML into the FrameLayout besides the TitlesFragment in the 'layout-land' version of the layout.

My problem stems from the fact that DetailsFragment is plugged into the MainActivity when in Landscape mode but gets it's own DetailsActivty if it is in Portrait mode.

The Button I have in my custom layout for the details-fragment calls a function in its onClick() that is called AddNewItem.

So when the Button was clicked in Landscape mode, it crashed, because there was no AddNewItem in the MainActivity. I solved this by using a BroadcastReceiver, so when the button is clicked, a method named AddNewItem in MainActivity.java instead broadcasts a custom event and i have a BroadcastReceiver that calls the AddNewItem in DetailsFragment.java.

It looks like this:

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "Intent Detected.", Toast.LENGTH_LONG).show();
        DetailsActivity  m = (DetailsActivity) DetailsActivity.getActivityInstance(); // see below for what getActivityInstance does

        LayoutInflater mInf = LayoutInflater.from(context);

        View myView = mInf.inflate(R.layout.customlayout, null);

        ((DetailsActivity) m).AddNewItem(myView);
    }
}

But this gives me:

08-11 13:37:50.687: E/AndroidRuntime(6766): java.lang.RuntimeException: Unable to start receiver in.falkeninc.umt_v0_9_8_1.MyReceiver: java.lang.NullPointerException

I am not sure what is happening. Because I am also using a static variable in DetailsActivity.java to be able to reach it inside the BroadcastReceiver. The code looks like this:

public class DetailsActivity extends SherlockFragmentActivity {
    ...
    public static SherlockFragmentActivity activityInstance;
    ...
    activityInstance = this;   // in the onCreate
    ...
    public static SherlockFragmentActivity getActivityInstance(){
       return activityInstance;
    }
}

Solution

  • My problem stems from the fact that DetailsFragment is plugged into the MainActivity when in Landscape mode but gets it's own DetailsActivty if it is in Portrait mode.

    This shouldn't be a problem. Although you have two activities you have the same DetailsFragment class in both of them. If a Button from that fragment is doing something then you should keep it at that fragment's level(that would be an ideal fragment, one that is self contained, a fragment that doesn't know or care where is put). If you do require the activity for the work in that method, you should add extra details.

    Also, if the behavior is common to both activities you could make a base activity holding that method and let the two current activities inherit from that, so it will be available to the fragment no matter what.

    public static SherlockFragmentActivity activityInstance;

    Don't keep static references to activities, you risk leaking them. Also, don't access activities from outside their own context. When an activity is not the one interacting with the user(it's onPause() has been called) that activity could as well be completely destroyed and trying to access it in another activity could bring you lots of problems.