这是RecyclerView.Adapter,它将Tasks(带有日期和标题)添加到“我的MainActivity”中。
public abstract class TaskAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
List<Item> items=new ArrayList<Item>();
TaskFragment taskFragment;
TaskAdapter(TaskFragment taskFragment){
this.taskFragment=taskFragment;
items =new ArrayList<>();
}
// getPosition() of lis;
public Item getItem(int position) {
return items.get(position);
}
// add item to list
public void addItem(Item item) {
items.add(item);
notifyItemInserted(getItemCount() - 1);
}
// add item to list's position
public void addItem(int location, Item item) {
items.add(location, item);
notifyItemInserted(location);
}
// NullPointerException Method
@Override
public int getItemCount() {
return items.size();
}
// remove list's item from position
public void removeItem(int location){
if(location>=0 && location<=getItemCount()-1){
items.remove(location);
notifyItemRemoved(location);
}
}
protected class TaskViewHolder extends RecyclerView.ViewHolder {
protected TextView title;
protected TextView date;
protected CircleImageView priority;
public TaskViewHolder(View itemView, TextView title, TextView date, CircleImageView priority) {
super(itemView);
this.title = title;
this.date = date;
this.priority=priority;
}
}
public TaskFragment getTaskFragment() {
return taskFragment;
}
}
!=空检查根本没有帮助。我认为问题在于方法调用的顺序。这是有问题的片段:
public abstract class TaskFragment extends Fragment {
protected RecyclerView recyclerView;
protected RecyclerView.LayoutManager layoutManager;
protected TaskAdapter adapter;
public void addTask(ModelTask newTask) {
int position = -1;
//this adapter.getItemCount() throws NullPointerException
for (int i = 0; i < adapter.getItemCount(); i ++) {
if (adapter.getItem(i).isTask()) {
ModelTask task = (ModelTask) adapter.getItem(i);
if (newTask.getDate() < task.getDate()) {
position = i;
break;
}
}
}
if (position != -1) {
adapter.addItem(position, newTask);
} else {
adapter.addItem(newTask);
}
}
public abstract void moveTask(ModelTask task);
}
也许有正确方法排序的方法?我可以避开这个例外吗?还是我的列表初始化错误?请帮我解决这个问题。
顺便说一下,这是来自堆栈跟踪的日志:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.densetsu, PID: 1871
java.lang.NullPointerException: Attempt to invoke virtual method 'int com.example.densetsu.adapter.TaskAdapter.getItemCount()' on a null object reference
at com.example.densetsu.fragment.TaskFragment.addTask(TaskFragment.java:20)
at com.example.densetsu.MainActivity.onTaskAdded(MainActivity.java:151)
at com.example.densetsu.dialog.AddingTaskDialogFragment$6.onClick(AddingTaskDialogFragment.java:182)
at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:162)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5536)
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:1397)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1192)
I/Process: Sending signal. PID: 1871 SIG: 9
Disconnected from the target VM, address: 'localhost:8600', transport: 'socket'
TaskAdapter是抽象的。我有两个类,它们扩展了TaskAdapter。这是CurrentTasksAdapter代码:
public class CurrentTasksAdapter extends TaskAdapter {
private static final int TYPE_TASK = 0;
private static final int TYPE_SEPARATOR = 1;
public CurrentTasksAdapter(CurrentTaskFragment taskFragment) {
super(taskFragment);
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
switch (viewType) {
case TYPE_TASK:
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.model_task, viewGroup, false);
TextView title = (TextView) v.findViewById(R.id.tvTaskTitle);
TextView date = (TextView) v.findViewById(R.id.tvTaskDate);
CircleImageView priority=(CircleImageView) v.findViewById(R.id.cvTaskPriority);
return new TaskViewHolder(v, title, date,priority);
default:
return null;
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
Item item = items.get(position);
if (item.isTask()) {
viewHolder.itemView.setEnabled(true);
final ModelTask task = (ModelTask) item;
final TaskViewHolder taskViewHolder = (TaskViewHolder) viewHolder;
final View itemView=taskViewHolder.itemView;
final Resources resources=itemView.getResources();
taskViewHolder.title.setText(task.getTitle());
if (task.getDate() != 0) {
taskViewHolder.date.setText(Utils.getFullDate(task.getDate()));
}
else {
taskViewHolder.date.setText(null);
}
itemView.setVisibility(View.VISIBLE);
// some code for setting color of text + animation of CircleImageView
}
CurrentTaskFragment,它扩展了TaskFragment:
public class CurrentTaskFragment extends TaskFragment {
OnTaskDoneListener onTaskDoneListener;
public CurrentTaskFragment() {
// Required empty public constructor
}
public interface OnTaskDoneListener {
void onTaskDone(ModelTask task);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
onTaskDoneListener = (OnTaskDoneListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnTaskDoneListener");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_current_task, container, false);
recyclerView = (RecyclerView) rootView.findViewById(R.id.rv_current_tasks);
layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
adapter = new CurrentTasksAdapter(this);
recyclerView.setAdapter(adapter);
// Inflate the layout for this fragment
return rootView;
}
@Override
public void moveTask(ModelTask task) {
onTaskDoneListener.onTaskDone(task);
}
}
在AddingTaskDialogFragment中,我有一个带有2个方法的接口:
public interface AddingTaskListener {
void onTaskAdded(ModelTask newTask);
void onTaskAddingCancel();
}
在MainActivity中,我先创建CurrentTaskFragment,然后重写接口的onTaskAdded方法:
TaskFragment currentTaskFragment;
@Override
public void onTaskAdded(ModelTask newTask) {
currentTaskFragment.addTask(newTask);
}
@Override
public void onTaskAddingCancel() {
Toast.makeText(this, "Task adding cancel", Toast.LENGTH_LONG).show();
}
即首先,我调用带有nullPointerException的addItem,由于链式反应(该方法获得空引用),因此下一个方法也将其引发nullPointerException
我在MainActivity中分配currentTaskFragment:
public class MainActivity extends AppCompatActivity
implements AddingTaskDialogFragment.AddingTaskListener,
CurrentTaskFragment.OnTaskDoneListener, DoneTaskFragment.OnTaskRestoreListener {
FragmentManager fragmentManager;
PreferenceHelper preferenceHelper;
TabAdapter tabAdapter;
//here
TaskFragment currentTaskFragment;
TaskFragment doneTaskFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PreferenceHelper.getInstance().init(getApplicationContext());
preferenceHelper = PreferenceHelper.getInstance();
fragmentManager = getFragmentManager();
runSplash();
setUI();
}
private void setUI() {
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText(R.string.current_task));
tabLayout.addTab(tabLayout.newTab().setText(R.string.done_task));
final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
tabAdapter = new TabAdapter(fragmentManager, 2);
viewPager.setAdapter(tabAdapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
//here
currentTaskFragment = (CurrentTaskFragment) tabAdapter.getItem(TabAdapter.CURRENT_TASK_FRAGMENT_POSITION);
doneTaskFragment = (DoneTaskFragment) tabAdapter.getItem(TabAdapter.DONE_TASK_FRAGMENT_POSITION);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DialogFragment addingTaskDialogFragment = new AddingTaskDialogFragment();
addingTaskDialogFragment.show(fragmentManager, "AddingTaskDialogFragment");
}
});
}
//two those methods
@Override
public void onTaskAdded(ModelTask newTask) {
currentTaskFragment.addTask(newTask);
}
@Override
public void onTaskAddingCancel() {
Toast.makeText(this, "Task adding cancel", Toast.LENGTH_LONG).show();
}
@Override
public void onTaskDone(ModelTask task) {
doneTaskFragment.addTask(task);
}
@Override
public void onTaskRestore(ModelTask task) {
currentTaskFragment.addTask(task);
}
}
问题已解决! 我的TabAdapter错误:
public class TabAdapter extends FragmentStatePagerAdapter {
private int numberOfTabs;
public static final int CURRENT_TASK_FRAGMENT_POSITION = 0;
public static final int DONE_TASK_FRAGMENT_POSITION = 1;
private CurrentTaskFragment currentTaskFragment;
private DoneTaskFragment doneTaskFragment;
public TabAdapter(FragmentManager fm, int numberOfTabs) {
super(fm);
this.numberOfTabs = numberOfTabs;
currentTaskFragment = new CurrentTaskFragment();
doneTaskFragment = new DoneTaskFragment();
}
@Override
public Fragment getItem(int i) {
switch (i) {
case 0:
// here i had "return new CurrentTaskFragment". It set currentTaskFragment to null
return currentTaskFragment;
case 1:
//the same with doneTaskFragment
return doneTaskFragment;
default:
return null;
}
}
感谢您的帮助!非常感谢<3:D