简体   繁体   中英

BroadcastReceiver in order to pass data from another Activity to Fragment

Let's say I have MainActivity where are few Fragments in ViewPager. I want to pass data from another Activity to one of these fragments. I'm doing this by BroadcastReceiver.

public class MyFragment extends Fragment {

    private MyFragmentReceiver mReceiver;

    public MyFragment() {
        super();
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mReceiver = new MyFragmentReceiver();
        getActivity().registerReceiver(mReceiver, new IntentFilter("fragmentUpdater"));
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_my, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        // My code here
    }

    public class MyFragmentReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            //My methods
        }

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mReceiver != null)
            getActivity().unregisterReceiver(mReceiver);
    }
}

So in my AnotherActivity I'm doing something like this:

Intent data = new Intent("fragmentUpdater");
MyApplication.getInstance().getMainActivity().sendBroadcast(data);

Where MyApplication is singleton which contains MainActivity. I noticed that BroadcastReceiver is putting something into logs, and I am wondering is that the best way to do it.

  1. Are there better ways to pass data from another activity to specific Fragment or call methods in that Fragment?
  2. Do I have to include something in AndroidManifest.xml related to BroadcastReceiver?

I would use LocalBroadcastManager instead, it gives you the following advantages :

  • You know that the data you are broadcasting won't leave your app, so don't need to worry about leaking private data.
  • It is not possible for other applications to send these broadcasts to your app, so you don't need to worry about having security holes they can exploit.
  • It is more efficient than sending a global broadcast through the system.

This is directly from the official docs

One alternative is using an interface for communicating between your activity and fragments. Example:

Interface

public interface MyInterface {

    void setSomeValue(int someValue);
    int getSomeValue();

}

Activity

public class MyActivity extends Activity implements MyInterface {

    private int someValue;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // do the usual stuff
    }

    // implement from MyInterface
    @Override
    public void setSomeValue(int someValue) {
        this.someValue = someValue;
    }

    // implement from MyInterface
    @Override
    public int getSomeValue() {
        return someValue;
    }

}

Fragment

public class MyFragment extends Fragment {

    private MyInterface mi;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mi = (MyInterface) context;
    }

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

        mi.setSomeValue(20);
        int someValue = mi.getSomeValue();

    }

}

You can use the interface to communicate between one or more activities, multiple fragments, views, tasks, services, etc etc etc. If you were to go this route, I would create a base activity which implements MyInterface and its methods, and have all other activities extend the base activity. I would even create a base fragment which calls onAttach(), and have all my other fragments extend this base fragment (so that I don't need to call onAttach() in every fragment).

UPDATE...

A base fragment would simply look like this:

public class BaseFragment extends Fragment {

    public MyInterface mi;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mi = (MyInterface) context;
    }

}

Now, MyFragment would just extend BaseFragment...

public class MyFragment extends BaseFragment {
    ...
}

There's no need now to attach or even declare MyInterface in any fragment extending BaseFragment, the base fragment already has a public instance of it. You just set/get/etc via your interface without any additional fuss:

mi.setSomeValue(20);

You may pass the data using Extras.

Intent data = new Intent("fragmentUpdater"); data.putExtra("STRING_YOU_NEED", strName);

and you can get the data inside onReceive function by :

String data_needed_here= extras.getString("STRING_YOU_NEED");

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