简体   繁体   中英

Android Broadcast Reciver Registering Multiple Listeners When used in a ViewPager

I have a ViewPager that builds a tabbed view with Fragments. In the Fragments I am registering aa Broadcast receiver for that Fragments DataSet (the data gets updated from a RESTApi.)

there are 4 tabs but it seems to be registering a new listener each time a tab is brought into view by the user which cant be good.

I register it in OnViewCreated() method

Should It be in create()?

My Fragment Class

public class DynamicFragment extends Fragment {

private static final String ARG_SECTION_NUMBER = "section_number";
private static final String ARG_TITLE = "title";
//.......
//.......

private Context context;
RecyclerView cardRecyclerView;
View view;
PresentationAdapter presentationAdapter;

public DynamicFragment() {
    // Required empty public constructor
    SyncApplication.getContext().registerReceiver(mReceiver, new IntentFilter(Sync.BROADCAST_FILTER));
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    this.context = context;

}

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

    sectionNumber = getArguments() != null ? getArguments().getInt(ARG_SECTION_NUMBER) : 1;
    title = getArguments() != null ? getArguments().getString(ARG_TITLE) : "Search";
}

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

    if (title.equals("Search")){
        Search search = new Search(inflater, container, savedInstanceState);
        return search.setView();
    }
    else{
        view = inflater.inflate(R.layout.fragment_dynamic, container, false);
        cardRecyclerView = view.findViewById(R.id.presentation_cards_recycler);
        presentationAdapter = new PresentationAdapter(context, getPresentationListByCategory());
        cardRecyclerView.setLayoutManager(new GridLayoutManager(context, 2));
        cardRecyclerView.setItemAnimator(new DefaultItemAnimator());
        cardRecyclerView.setAdapter(presentationAdapter);

        // Inflate the layout for this fragment
    }
    return view;
}

public void updateCardView() {
    if (presentationList != null && presentationList.size() > 0) {
        if (presentationAdapter != null) {
            presentationAdapter.setPresentationList(getPresentationListByCategory());
            presentationAdapter.notifyDataSetChanged();
        }
    }
}

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    if (context != null) {
        context.registerReceiver(mReceiver, new IntentFilter(Sync.BROADCAST_FILTER));
    }
}

public ArrayList<Presentation> getPresentationListByCategory() {
    dbManager = new DbManager(context);
    presentationList = dbManager.getAllPresentations();
    ArrayList<Presentation> presentationsByCategory = new ArrayList();

    for (Presentation presentation : presentationList) {
        if (presentation.getCategory_name().equals(title)) {
            presentationsByCategory.add(presentation);
        }
    }
    return presentationsByCategory;
}

public static DynamicFragment newInstance(String val) {
    DynamicFragment fragment = new DynamicFragment();
    Bundle args = new Bundle();
    args.putString("title", val);
    fragment.setArguments(args);
    return fragment;
}

BroadcastReceiver mReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        // Do what you need in here
        String message = intent.getStringExtra("syncMessage");
        Log.d("Fragment Reciever", message);
        if (message.equals("DownloadComplete")) {
            updateCardView();
        }
    }
};

}

There are two places where you register a BroadcastReceiver in your Fragment :

public DynamicFragment() {
    // Required empty public constructor
    SyncApplication.getContext().registerReceiver(mReceiver, new IntentFilter(Sync.BROADCAST_FILTER));
}

and

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    if (context != null) {
        context.registerReceiver(mReceiver, new IntentFilter(Sync.BROADCAST_FILTER));
    }
}

Since they both use the same IntentFilter , this is already one too many. In addition to that, you do not unregister any of the registered BroadcastReceiver s, so they remain active.

You should register a BroadcastReceiver eg in onResume() and unregister it in onPause() . See also the Broadcasts Overview

You can register the receiver in the activity instead of in the fragment.

Once you receive the broadcast in the activity, you can get the current instance of the fragment displayed in view pager and then call the updateCardView() method for that fragment.

This way you only register for the receiver once in activity.

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