【问题标题】:RecyclerView Adapter Attached to Previous Fragment附加到上一个片段的 RecyclerView 适配器
【发布时间】:2015-12-22 15:17:05
【问题描述】:

我有一个Activity,其中有一个Fragment 和一个RecyclerView。当单击RecyclerView 项目之一时,将在原来的顶部添加一个新的Fragment 并添加到后堆栈。这个新的Fragment 与之前的Fragment 具有相同的layout,并使用相同Adapter 的不同实例。当按下后退按钮时会出现问题,将第二个Fragment 从堆栈中弹出,然后再次单击第一个Fragment 中的一个项目,应用程序崩溃并显示NullPointerException

12-22 08:50:53.283 20747-20747/com.example.app E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.app, PID: 20747
    java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.app.ui.activity.MainActivity.revealFragment(android.support.v4.app.Fragment)' on a null object reference
        at com.example.app.ui.fragment.CampusFragment.onItemClickListener(SecondFragment.java:115)
        at com.example.app.ui.adapter.LauncherAdapter$ViewHolder.onClick(LauncherAdapter.java:68)
        at android.view.View.performClick(View.java:4780)
        at android.view.View$PerformClick.run(View.java:19866)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5254)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

但是第二个FragmentonItemClickListener 被调用,而不是第一个。第二个Fragment 不再附加,因此onItemClickListener 中的getActivity() 产生NullPointerException,但第二个Fragment 根本不应该被调用。两个Fragment 类都有一个RecyclerView,其设置方式相同:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_main, container, false);

    mAdapter = new LauncherAdapter(getContext(), mDataSet);
    mAdapter.setOnItemClickListener(this);
    GridLayoutManager layoutManager = new GridLayoutManager(getContext(), 2);
    ItemTouchHelper touchHelper = new ItemTouchHelper(onItemTouch());

    RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recycler);
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setAdapter(mAdapter);
    touchHelper.attachToRecyclerView(recyclerView);

    return view;
}

为每个创建一个新的LauncherAdapter

public class LauncherAdapter extends RecyclerView.Adapter<LauncherAdapter.ViewHolder> implements ItemTouchHelperAdapter {

    public interface OnItemClickListener {
        void onItemClickListener(@StringRes int title);
    }

    private static OnItemClickListener sListener;

    private Context mContext;

    private List<LauncherCard> mDataset;

    public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        private int mId;

        public ImageView iconView;
        public TextView titleView;

        public ViewHolder(View itemView) {
            super(itemView);

            iconView = (ImageView) itemView.findViewById(R.id.icon);
            titleView = (TextView) itemView.findViewById(R.id.title);

            itemView.setOnClickListener(this);
        }

        public void setId(@StringRes int id) {
            mId = id;
        }

        @Override
        public void onClick(View view) {
            sListener.onItemClickListener(mId);
        }
    }

    public LauncherAdapter(Context context, List<LauncherCard> dataset) {
        mContext = context;
        mDataset = dataset;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.view_card_launcher, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.iconView.setImageResource(mDataset.get(position).getDrawable());
        holder.titleView.setText(mDataset.get(position).getId());
        holder.setId(mDataset.get(position).getId());
    }

    @Override
    public int getItemCount() {
        return mDataset.size();
    }

    @Override
    public void onItemMove(int fromPosition, int toPosition, String saveLocation) {
        if (fromPosition < toPosition) {
            Collections.rotate(mDataset.subList(fromPosition, toPosition + 1), -1);
        } else {
            Collections.rotate(mDataset.subList(toPosition, fromPosition + 1), + 1);
        } notifyItemMoved(fromPosition, toPosition);

        SharedPreferences.Editor editor = mContext.getSharedPreferences("recycler_positions", Context.MODE_PRIVATE).edit();
        editor.putString(saveLocation, new Gson().toJson(mDataset)).apply();
    }

    @Override
    public void onItemDismiss(int position) {
        // Not utilized
    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        sListener = listener;
    }
}

为什么要调用第二个FragmentonItemClickListener 而不是第一个?第二个FragmentLauncherAdapter 是否也以某种方式附加到第一个FragmentRecyclerView 上?您不能在一个Context 中包含两个相同Adapter 的实例吗?

【问题讨论】:

    标签: android android-fragments android-recyclerview android-adapter android-context


    【解决方案1】:

    不要将你的 Listener 声明为静态的。改变

    private static OnItemClickListener sListener;
    

    private OnItemClickListener mListener;
    

    您使用静态可能是为了可以从您的ViewHolder 访问。为了克服它,将它传递给两个构造函数,AdapterViewHolder

    public LauncherAdapter(Context context, List<LauncherCard> dataset,  OnItemClickListener listener) {
        mContext = context;
        mDataset = dataset;
        mListener = listener;
    }
    

    public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        private int mId;
    
        public ImageView iconView;
        public TextView titleView;
        private OnItemClickListener mListener;
        public ViewHolder(View itemView, OnItemClickListener listener) {
            super(itemView)
            mListener = listener; 
        }
    

    并在您的onClick 中使用mListener

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-09
      • 2021-06-21
      • 2018-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多