【问题标题】:Interface observer pattern: null object reference接口观察者模式:空对象引用
【发布时间】:2015-10-14 17:25:46
【问题描述】:

不确定我的观察者模式有什么问题:

我已将我的界面定义为:

public interface OnBackFilterPressListener {
    public ArrayList<FoodType> filterFoodType ();
}

当我按下后退按钮时,我希望激活监听器 - 所有这些代码都在我的 activity 类中:

        back.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                    onBackFilterPressListener.filterFoodType();
}
}

在我的适配器类中,我有以下代码:

public class RandomRecyclerViewAdapter  extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements SearchActivity.OnBackFilterPressListener {

       @Override
    public ArrayList<FoodType> filterFoodType() {
        return foodTypes;
    }

}

当我在活动中按下后退按钮时,我只想在我的活动类中返回适配器中的数据数组。

但是我收到了这个错误:

java.lang.NullPointerException:尝试调用接口方法 'java.util.ArrayList com.example.simon..SearchActivity$OnBackFilterPressListener.filterFoodType()' 在空对象引用上

foodType 肯定存在 - 适配器将数据加载到活动中,我可以看到它显示在 android 模拟器上。单击返回按钮时出现此错误。

【问题讨论】:

  • 显然onBackFilterPressListenernull。你是怎么初始化的?
  • 也许这就是问题所在......我刚才说 OnBackFilterPressListener onBackFilterPressListener 作为我的成员变量。我应该如何初始化它?
  • RandomRecyclerViewAdapter 的实例分配给它。
  • @Simon SearchActivity 是一个 Activity 类,对吧? recyclerview 附在哪里?是为了不同的活动吗?
  • 所以 SearchActivity 是一个活动类,它持有对片段的引用。片段内部是一个recyclerview,适配器用于该recyclerview。这真的没关系,因为观察者模式肯定会在你放置它的任何地方观察它,并且一旦你的事件发生就会被触发? Activity、Fragment和Adapter都是同时在屏幕上同时显示的,所以它不像Activity或者Fragment里面有onStop或者onPaused。

标签: android interface


【解决方案1】:

我通过关注这个帖子并有点创意来实现它:

How to create our own Listener interface in android?

我写了一个自定义对象来防止空对象引用作为使用接口,我首先要创建对象:

public class BackFilterEvent implements Serializable {

    private OnEventListener mOnEventListener;

    public void setOnEventListener(OnEventListener listener) {
        mOnEventListener = listener;
    }

    public ArrayList<FoodType> doEvent() {
        if (mOnEventListener != null) {
            return mOnEventListener.onEvent(); 
        }
        return null;
    }

    public interface OnEventListener {
        ArrayList<FoodType> onEvent();
    }

}

然后在我的 Activity 类中,我创建了对象:

BackFilterEvent backFilterEvent = new BackFilterEvent();

我将它传递到我的代码中需要的地方。在我的例子中,我有一个活动在片段中使用 recyclerview 适配器来提供片段。我一直传递这个对象,直到它到达 recyclerview 适配器。

将对象从 Activity 传递到 Fragment:

            FilterSearchFragment filterSearchFragment = new FilterSearchFragment();
            Bundle bundle = new Bundle();
            bundle.putSerializable("listener", backFilterEvent);
            filterSearchFragment.setArguments(bundle);
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.fragment_container, filterSearchFragment)
                    .commit();

从片段传递到适配器:

    Bundle bundle = getArguments();
    BackFilterEvent backFilterEvent = (BackFilterEvent) bundle.getSerializable("listener");
    RandomRecyclerViewAdapter randomRecyclerViewAdapter  = new RandomRecyclerViewAdapter(getContext(), backFilterEvent);

在我的适配器构造函数中,我将它设置为在我从活动类中调用它时完成工作:

    this.backFilterEvent = backFilterEvent;
    backFilterEvent.setOnEventListener(new BackFilterEvent.OnEventListener() {
        @Override
        public ArrayList<FoodType> onEvent() {
            return foodTypes;
        }
    });

在我的活动类的后退按钮中,我调用了监听器,这将触发适配器类中的工作:

    back.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

                ArrayList<FoodType> foodTypes = backFilterEvent.doEvent(); }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-06
    • 2012-07-09
    • 1970-01-01
    • 2013-02-12
    • 1970-01-01
    • 1970-01-01
    • 2016-02-20
    • 2023-04-10
    相关资源
    最近更新 更多