我的Activity
Fragment
RecyclerView
。单击其中一个RecyclerView
项目时,会在原始项目的顶部添加新的Fragment
并添加到后台堆栈。此新Fragment
与之前的layout
具有相同的Fragment
,并使用相同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)
但第二个onItemClickListener
的{{1}}被调用,而不是第一个。第二个Fragment
不再附加,因此Fragment
中的getActivity()
生成onItemClickListener
,但第二个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;
}
}
的{{1}}而不是第一个?{1}}?第二个onItemClickListener
的{{1}}是否也以某种方式附加到第一个Fragment
的{{1}}?你能不能在一个LauncherAdapter
中有两个相同Fragment
的实例?
答案 0 :(得分:1)
不要将您的侦听器声明为静态。变化
private static OnItemClickListener sListener;
到
private OnItemClickListener mListener;
您可以通过ViewHolder
访问静态。要克服它,请将其传递给构造函数Adapter
和ViewHolder
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;
}
并在mListener
onClick