【问题标题】:EventBus called multiple times in ViewPager Fragment在 ViewPager Fragment 中多次调用 EventBus
【发布时间】:2018-03-10 11:34:54
【问题描述】:

我有一个这样的 ViewPagerAdapter

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();

    }
}

这个 ViewPagerAdapter 正在使用 MoviePagerFragment 类中的这个静态方法调用 MoviePagerFragment

public static Fragment start(List<MovieCategory> movieCategoryList, int position, String from) {
    Fragment moviePagerFragment = new MoviePagerFragment();
    Bundle basket = new Bundle();
    basket.putString("from",from);
    basket.putInt("viewpager-position",position);
    basket.putParcelableArrayList("movie_category_list", (ArrayList<? extends Parcelable>) movieCategoryList);
    basket.putParcelableArrayList("movie_list", (ArrayList<? extends Parcelable>) movieCategoryList.get(position).getMovies());
    moviePagerFragment.setArguments(basket);
    return moviePagerFragment;
}

现在我在 MoviePagerFragment 中像这样注册/取消注册 EventBus

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    super.onStop();
    EventBus.getDefault().unregister(this);
}

然后我有一个方法来订阅像这样调度的事件

@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();
}

MovieBuyEvent 正在像这样从 RecyclerViewAdapter 的 ViewHolder 类中的项目的 ItemClick 广播

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(最终的 MovieBuyEvent 事件)

方法也被调用了很多次,这使得 Dialog 出现多次。那么我应该在 ViewPagerAdapter 调用的 Fragment 中哪里注册/取消注册 EventBus?

【问题讨论】:

  • 您在哪里以及如何广播 MovieBuyEvent?
  • 我正在从 RecyclerViewAdapter 的 ViewHolder onClick 监听器中广播 MovieBuyEvent,请再次检查问题,我已更新代码。
  • 你的片段有多少个实例?可以在片段的每个实例中调用它。

标签: android android-studio android-fragments android-dialog greenrobot-eventbus


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您应该将您的注册事件从onStart() 移动到onCreateView()。这是因为 onStart 总是called when the Fragment is visible to the user

    然后尝试在onDestroy()注销:

    @Override
    public void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2013-10-23
        • 2012-11-06
        • 1970-01-01
        • 1970-01-01
        • 2012-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多