我有一个包含三个片段的视图寻呼机(A-> B-> C):
片段A 有两个edittexts和一个保存按钮; 片段B 有一个工具栏和一个可滚动的textview; Fragment C 有一个设置为LinearLayout的RecyclerView。
在应用启动时,我滑动到片段B,然后在ListFragment(片段C)的视图适配器getItemCount()
上获得NPE。这发生在物理测试设备(API 21)上,但不在任何仿真器上(API 18-23)。
可能是什么原因?
编辑:添加 HomeActivity.class 界面方法:
@Override
public ArrayList<String> getList() {
titleSharedPref = getSharedPreferences(TITLE_PREF, Context.MODE_PRIVATE);
try {
this.songArrayList = (ArrayList<String>) ObjectSerializer
.deserialize(titleSharedPref.getString(TITLE_PREF, ObjectSerializer.serialize(new ArrayList<String>())));
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return this.songArrayList;
}
ListFragment.class :
public class ListFragment extends Fragment {
private RecyclerView recyclerView;
private SongRecyclerViewAdapter recyclerViewAdapter;
private FragmentCommunicator communicator;
public ListFragment() {
// Required empty constructor
}
public static ListFragment newInstance() {
return new ListFragment();
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof FragmentCommunicator) {
communicator = (FragmentCommunicator) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement FragmentCommunicator");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_song_list, container, false);
// Set the adapter
if (view instanceof RecyclerView) {
Context context = view.getContext();
recyclerView = (RecyclerView) view;
recyclerView.setLayoutManager(new LinearLayoutManager(context));
recyclerViewAdapter = new SongRecyclerViewAdapter(communicator.getList(), communicator);
recyclerView.setAdapter(recyclerViewAdapter);
}
ItemTouchHelper.SimpleCallback simpleItemCallBack = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT){
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int pos = viewHolder.getAdapterPosition();
if (communicator.remove(pos)) {
recyclerViewAdapter.notifyItemRemoved(pos);
recyclerViewAdapter.notifyItemRangeChanged(pos, recyclerViewAdapter.getItemCount());
}
}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemCallBack);
itemTouchHelper.attachToRecyclerView(recyclerView);
return view;
}
/**
* {@link RecyclerView.Adapter} that can display a {@link ArrayList} and makes a call to the
* specified {@link FragmentCommunicator}.
*/
public class SongRecyclerViewAdapter extends RecyclerView.Adapter<SongRecyclerViewAdapter.ViewHolder> {
private final ArrayList<String> mValues;
private final FragmentCommunicator communicator;
public SongRecyclerViewAdapter(ArrayList<String> items, FragmentCommunicator communicator) {
this.mValues = items;
this.communicator = communicator;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false));
}
public class ViewHolder extends RecyclerView.ViewHolder {
public final View mView;
public final TextView mContentView;
public String mItem;
public ViewHolder(View view) {
super(view);
mView = view;
mContentView = (TextView) view.findViewById(R.id.content);
}
@Override
public String toString() {
return super.toString() + " '" + mContentView.getText() + "'";
}
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.mItem = mValues.get(position);
holder.mContentView.setText(holder.mItem);
holder.mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (null != communicator) {
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
communicator.respond(holder.mItem, HomeActivity.MODE_PICK);
}
}
});
}
@Override
public int getItemCount() {
return mValues.size();
}
}
@Override
public void onDetach() {
super.onDetach();
// kill
communicator = null;
recyclerViewAdapter = null;
}
}
编辑:删除了第二个问题:adding ViewPager listener.
谢谢大家!
答案 0 :(得分:2)
首先,您应该认真考虑清理碎片代码。我建议您将viewholder和adapter解压缩到自己的类中。通过将代码隔离到特定的需求区域,这将极大地帮助您完成代码。
其次,考虑在视图中进行视图工作,而不是在适配器的onBindViewHolder()方法中。您可以创建一个名为populateViews()的方法,然后传入将填充视图中视图的数据。
第三,您确定数据实际上是传递给RecyclerView吗?我的猜测是,不,你可能没有传递数据,因此它正在抛出一个NPE。请记住,FragmentPagerAdapter将尝试启动至少三个片段 - 可见的片段,左侧的片段和右侧的片段。在您的情况下,当您滑动到片段B时,它正在尝试填充片段C中的RecyclerView,但您还没有任何数据。
至于如何将数据从片段A传递到片段B,而无需用户点击某些内容......只需将片段A的EditTexts内容传递给Activity,然后将该数据发送到片段B.您可以间隔执行此操作(例如,在输入每个字符后)或用户暂停时,或者当FragmentPagerAdapter开始您可以使用的滑动时甚至还有回调。
答案 1 :(得分:0)
@ rf43感谢您的帮助。 这是我的HTC One M7测试设备的设备特定问题。我手动卸载调试apk(安装完毕)并再次安装。现在我的应用程序按设计工作。设备一定存在内存问题。