Arn
Arn

Reputation: 600

android calling a MainActivity function from a fragment

I'm new to android and I'm trying to get a hang of creating and using Fragments.

I have a fragment that shows a simple list of multiple dates to choose from and implements an onClickListener. The idea is once a user chooses a date, the fragments sends the date back to the MainActivity which then runs a query in database and sends the database response to another fragment.

I'm stuck on the point of sending the date back to MainActivity, elegantly. I can't find much info. I found this:

 Activity activity = getActivity();
 if(activity instanceof MyActivity){
      MyActivity myactivity = (MyActivity) activity;
      myactivity.myMethod();
}

I'm very new to this but this seems hacky to me. Is this the right way or is there another way?

Any input is appreciated

Upvotes: 0

Views: 168

Answers (2)

Ferdous Ahamed
Ferdous Ahamed

Reputation: 21766

YES this is absolutely right. You can use this, if you are not sure that your Fragment is attached to Activity

You can also achieve this by using Interface, using an EventBus like LocalBroadcastManager, or starting a new Activity with an Intent and some form of flag passed into its extras Bundle or something else.

Here is an example about using Interface:

1. Add function sendDataToActivity() into the interface (EventListener).

//EventListener.java

public interface EventListener {

    public void sendDataToActivity(String data);
}

2. Implement this functions in your MainActivity.

// MainActivity.java

public class MainActivity extends AppCompatActivity implements EventListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public void sendDataToActivity(String data) {
        Log.i("MainActivity", "sendDataToActivity: " + data);
    }
}

3. Create the listener in MyFragment and attach it to the Activity.

4. Finally, call function using listener.sendDataToActivity("Hello World!").

// MyFragment.java 

public class MyFragment extends Fragment {

    private EventListener listener;

    @Override
    public void onAttach(Activity activity)
    {
        super.onAttach(activity);
        if(activity instanceof EventListener) {
            listener = (EventListener)activity;
        } else {
            // Throw an error!
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_my, container, false);

        // Send data
        listener.sendDataToActivity("Hello World!");

        return view;
    }

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

        listener = null;
    }
}

Hope this will help~

Upvotes: 1

Giorgio Antonioli
Giorgio Antonioli

Reputation: 16224

I prefer the interface based approach because is very clean. You can declare a nested interface in your Fragment or an external one:

interface OnMyStuffListener {
    void myMethod();
}

Make the Activity to implement that interface:

public class MainActivity extends Activity implements OnMyStuffListener {
    @Override
    public void myMethod() {
        // Do whatever you want.
    }
}

The Fragment will be attached to the Activity so you can check the instance of the Context and cast it to the Activity:

public class MyFragment extends Fragment implements View.OnClickListener {
    private OnMyStuffListener mListener;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnMyStuffListener) {
            mListener = (OnMyStuffListener) context;
        } else {
            throw new IllegalArgumentException("The context " + context.getClass().getName() +
                    "must implement " + OnMyStuffListener.class.getName());
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        // Release it avoiding memory leak.
        mListener = null;
    }


    @Override
    public void onClick(View v) {
        mListener.myMethod();
    }
}

Upvotes: 2

Related Questions