Android 在ViewPager片段中多次调用EventBus

Android 在ViewPager片段中多次调用EventBus,android,android-studio,android-fragments,android-dialog,greenrobot-eventbus,Android,Android Studio,Android Fragments,Android Dialog,Greenrobot Eventbus,我有一个像这样的可视页面雷达 public class ViewPagerAdapter extends FragmentStatePagerAdapter { List<MovieCategory> movieCategoryList; public ViewPagerAdapter(FragmentManager fm, List<MovieCategory> movieCategoryList) { super(fm);

我有一个像这样的可视页面雷达

public class ViewPagerAdapter extends FragmentStatePagerAdapter {
    List<MovieCategory> movieCategoryList;

    public ViewPagerAdapter(FragmentManager fm, List<MovieCategory> movieCategoryList) {
        super(fm);
        this.movieCategoryList = movieCategoryList;
    }

    @Override
    public Fragment getItem(int position) {

        return MoviePagerFragment.start(movieCategoryList, position, "listing");

    }

    @Override
    public int getCount() {
        return movieCategoryList.size();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return movieCategoryList.get(position).getCategoryTitle();

    }
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(final MovieBuyEvent event) {
    final double moviePrice = Double.parseDouble(event.getMoviesItem().getMoviePrice());
    final Dialog dialog = new Dialog(getActivity());
    dialog.setContentView(R.layout.channel_buy_dialog);
    dialog.setCancelable(true);
    ImageView imageView = (ImageView) dialog.findViewById(R.id.imageView);
    TextView tvName = (TextView) dialog.findViewById(R.id.tvName);
    Button bBuy = (Button) dialog.findViewById(R.id.bBuy);
    Button bCancel = (Button) dialog.findViewById(R.id.bCancel);
    final TextView tvPrice = (TextView) dialog.findViewById(R.id.tvPrice);
    final Spinner spinner = (Spinner) dialog.findViewById(R.id.spinner);
    Picasso.with(getActivity()).load(event.getMoviesItem().getMoviePicture()).placeholder(R.mipmap.placeholder).into(imageView);
    tvName.setText(event.getMoviesItem().getMovieName());
    tvPrice.setText(event.getMoviesItem().getMovieName());
    dialog.show();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    public ViewHolder(View view) {
        super(view);
        itemView.setClickable(true);
        itemView.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        position = getAdapterPosition();
        MoviesItem moviesItem = moviesItemList.get(position);
        try {
            MovieBuyEvent movieBuyEvent = new MovieBuyEvent();
                movieBuyEvent.setMoviesItem(moviesItem);
                EventBus.getDefault().post(movieBuyEvent);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}
然后我有一个方法订阅像这样发送的事件

public class ViewPagerAdapter extends FragmentStatePagerAdapter {
    List<MovieCategory> movieCategoryList;

    public ViewPagerAdapter(FragmentManager fm, List<MovieCategory> movieCategoryList) {
        super(fm);
        this.movieCategoryList = movieCategoryList;
    }

    @Override
    public Fragment getItem(int position) {

        return MoviePagerFragment.start(movieCategoryList, position, "listing");

    }

    @Override
    public int getCount() {
        return movieCategoryList.size();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return movieCategoryList.get(position).getCategoryTitle();

    }
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(final MovieBuyEvent event) {
    final double moviePrice = Double.parseDouble(event.getMoviesItem().getMoviePrice());
    final Dialog dialog = new Dialog(getActivity());
    dialog.setContentView(R.layout.channel_buy_dialog);
    dialog.setCancelable(true);
    ImageView imageView = (ImageView) dialog.findViewById(R.id.imageView);
    TextView tvName = (TextView) dialog.findViewById(R.id.tvName);
    Button bBuy = (Button) dialog.findViewById(R.id.bBuy);
    Button bCancel = (Button) dialog.findViewById(R.id.bCancel);
    final TextView tvPrice = (TextView) dialog.findViewById(R.id.tvPrice);
    final Spinner spinner = (Spinner) dialog.findViewById(R.id.spinner);
    Picasso.with(getActivity()).load(event.getMoviesItem().getMoviePicture()).placeholder(R.mipmap.placeholder).into(imageView);
    tvName.setText(event.getMoviesItem().getMovieName());
    tvPrice.setText(event.getMoviesItem().getMovieName());
    dialog.show();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    public ViewHolder(View view) {
        super(view);
        itemView.setClickable(true);
        itemView.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        position = getAdapterPosition();
        MoviesItem moviesItem = moviesItemList.get(position);
        try {
            MovieBuyEvent movieBuyEvent = new MovieBuyEvent();
                movieBuyEvent.setMoviesItem(moviesItem);
                EventBus.getDefault().post(movieBuyEvent);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}
MovieBuyEvent是从RecycleServiceAdapter的ViewHolder类中的一个项目的ItemClick广播的,如下所示

public class ViewPagerAdapter extends FragmentStatePagerAdapter {
    List<MovieCategory> movieCategoryList;

    public ViewPagerAdapter(FragmentManager fm, List<MovieCategory> movieCategoryList) {
        super(fm);
        this.movieCategoryList = movieCategoryList;
    }

    @Override
    public Fragment getItem(int position) {

        return MoviePagerFragment.start(movieCategoryList, position, "listing");

    }

    @Override
    public int getCount() {
        return movieCategoryList.size();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return movieCategoryList.get(position).getCategoryTitle();

    }
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(final MovieBuyEvent event) {
    final double moviePrice = Double.parseDouble(event.getMoviesItem().getMoviePrice());
    final Dialog dialog = new Dialog(getActivity());
    dialog.setContentView(R.layout.channel_buy_dialog);
    dialog.setCancelable(true);
    ImageView imageView = (ImageView) dialog.findViewById(R.id.imageView);
    TextView tvName = (TextView) dialog.findViewById(R.id.tvName);
    Button bBuy = (Button) dialog.findViewById(R.id.bBuy);
    Button bCancel = (Button) dialog.findViewById(R.id.bCancel);
    final TextView tvPrice = (TextView) dialog.findViewById(R.id.tvPrice);
    final Spinner spinner = (Spinner) dialog.findViewById(R.id.spinner);
    Picasso.with(getActivity()).load(event.getMoviesItem().getMoviePicture()).placeholder(R.mipmap.placeholder).into(imageView);
    tvName.setText(event.getMoviesItem().getMovieName());
    tvPrice.setText(event.getMoviesItem().getMovieName());
    dialog.show();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    public ViewHolder(View view) {
        super(view);
        itemView.setClickable(true);
        itemView.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        position = getAdapterPosition();
        MoviesItem moviesItem = moviesItemList.get(position);
        try {
            MovieBuyEvent movieBuyEvent = new MovieBuyEvent();
                movieBuyEvent.setMoviesItem(moviesItem);
                EventBus.getDefault().post(movieBuyEvent);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}
现在的问题是,每次我滑动一个片段,EventBus都会被注册和注销很多次,如此等等

onMessageEvent(最终电影购买事件)


方法也被多次调用,使对话框多次出现。那么,在ViewPagerAdapter调用的片段中,我应该在哪里注册/取消注册EventBus呢?

如果有多个片段已注册以侦听
MovieBuyEvent
广播,它们都将响应,这是理所当然的。如果您在包含可解决问题的viewpager的活动或片段中注册了事件侦听器。

如果您有多个片段已注册以侦听
MovieBuyEvent
广播,则它们都将响应,这是理所当然的。如果您在包含viewpager的活动或片段中注册了事件侦听器,则可以解决您的问题。

您应该将注册事件从
onStart()
移动到
onCreateView()
。这是因为onStart始终是

然后尝试在
onDestroy()中注销:


您应该将注册事件从
onStart()
移动到
onCreateView()
。这是因为onStart始终是

然后尝试在
onDestroy()中注销:


如果您从未在viewpager中使用过setOffscreenPageLimit,则应限制为一个。
默认情况下,viewpager将加载三个片段,一个是您刚刚打开父片段/活动时看到的当前片段,另外两个片段依次加载。初始化viewpager时,尝试将OffScreenPageLimit设置为1。基本上,它将一次加载一个片段,而不是每个viewpager滚动加载三个片段。当您使用事件总线时,它一次只能访问一个片段,而不是所有正在使用的片段。

如果您从未在viewpager中使用过setOffscreenPageLimit,则应限制为一个片段。
默认情况下,viewpager将加载三个片段,一个是您刚刚打开父片段/活动时看到的当前片段,另外两个片段依次加载。初始化viewpager时,尝试将OffScreenPageLimit设置为1。基本上,它将一次加载一个片段,而不是每个viewpager滚动加载三个片段。当您使用事件总线时,它一次只能访问一个片段,而不是所有正在使用的片段。

您如何以及在何处播放MovieBuyEvent?我正在从RecycleServiceAdapter的ViewHolder onClick listener播放MovieBuyEvent,请再次检查问题,我已经更新了代码。你的片段有多少个实例?它可以在您片段的每个实例中调用。您如何以及在何处广播MovieBuyEvent?我正在从RecycleServiceAdapter的ViewHolder onClick侦听器广播MovieBuyEvent,请再次检查问题,我已更新代码。您片段的实例有多少?可以在片段的每个实例中调用它。