我已经在应用程序上工作了很长时间。这个应用程序应该采用姓氏并测量访问时间,这是恒定的(30分钟)。我有一个Family对象,其中包含名称,成员数和访问结束等信息,表示为未来的毫秒值。
我实现定时器部分的方法只是创建一个名为CountDownManager的类,它负责更新和计算列出的所有系列视图持有者的剩余时间。
问题在于,每当我从回收站视图中删除一个族(列表项)时,我的CountDownManager都会出现NullPointerException错误。
基本上我认为CountDownManager正在尝试访问数据集中不再可用的族。我试图通过简单地同步我删除一个系列的部分来解决这个问题,但它仍然会因同样的错误而崩溃。
以下是我的FamiliesAdapter的代码:
package bikurim.silverfix.com.bikurim.utils.managers;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import bikurim.silverfix.com.bikurim.Constants;
import bikurim.silverfix.com.bikurim.adapters.holders.FamilyViewHolder;
import bikurim.silverfix.com.bikurim.utils.interfaces.EventListener;
import bikurim.silverfix.com.bikurim.utils.Utils;
/**
* Created by David on 07/07/2016.
* @author David
* Inspired by MiguelLavigne
*
* A custom CountDownTimer class, which takes care of all the running timers
*/
public class CountDownManager {
private final long interval;
private long base;
// Holds references for all the visible text views
private ArrayList<FamilyViewHolder> holders;
private EventListener listener;
public CountDownManager(long interval, EventListener listener) {
this.listener = listener;
this.interval = interval;
holders = new ArrayList<>();
}
public void start() {
base = System.currentTimeMillis();
handler.sendMessage(handler.obtainMessage(MSG));
}
public void stop() {
handler.removeMessages(MSG);
}
public void reset() {
synchronized (this) {
base = System.currentTimeMillis();
}
}
public void addHolder(FamilyViewHolder holder) {
synchronized (holders) {
if(holder.isHolderAdded == false) {
holders.add(holder);
holder.isHolderAdded = true;
}
}
}
public void removeHolder(FamilyViewHolder holder) {
synchronized (holders) {
holders.remove(holder);
}
}
synchronized void onTick(long elapsedTime) {
try {
if(!holders.isEmpty()) {
long timeLeft, lengthOfVisit;
for (FamilyViewHolder holder : holders) {
lengthOfVisit = holder.family.whenInMillis - base;
timeLeft = lengthOfVisit - elapsedTime;
if(timeLeft > 0) {
Log.d("Time left:", "" + timeLeft);
if(timeLeft <= Constants.Values.ALERT_TIME && !holder.isStrokeChanged) {
listener.onLessThanMinute(holder);
}
holder.family.timeLeft = timeLeft;
holder.timeLeft.setText(Utils.updateFormatTime(timeLeft));
} else {
listener.onFinish(holder);
removeHolder(holder);
}
}
}
} catch (ConcurrentModificationException e) {
Log.d("Concurrent Error", "App will shut down now");
e.printStackTrace();
}
}
public void clear() {
holders.clear();
}
private static final int MSG = 1;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
synchronized (CountDownManager.this) {
long elapsedTime = System.currentTimeMillis() - base;
onTick(elapsedTime);
sendMessageDelayed(obtainMessage(MSG), interval);
}
}
};
}
这是CountDownManager:
ItemTouchHelper.SimpleCallback callback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) {
final int pos = viewHolder.getAdapterPosition();
AlertDialog.Builder builder = new AlertDialog.Builder(FamilyListActivity.this);
builder.setMessage(R.string.confirmation_message)
.setPositiveButton(R.string.proceed_dialog, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
synchronized (families) {
Family family = families.get(pos);
GenericViewHolder holder = null;
try {
holder = (GenericViewHolder) viewHolder;
} catch (ClassCastException e) {
e.printStackTrace();
}
String whereClause = FamiliesTablesContract.DATE_COLUMN + "=?";
String args[] = new String[] {"" + family.date};
Cursor cursor = dataManager.query(FamiliesTablesContract.TABLE_NAME, whereClause, args);
int entryId = 0;
try {
cursor.moveToFirst();
entryId = cursor.getInt(cursor.getColumnIndexOrThrow(FamiliesTablesContract._ID));
} catch (Exception e) {
e.printStackTrace();
}
reminderManager.cancelReminder(entryId);
String name = family.name;
adapter.removeData(pos, holder);
dialog.dismiss();
}
}
}).setNegativeButton(R.string.cancel_dialog, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
adapter.notifyItemChanged(pos);
dialog.dismiss();
}
});
builder.show();
}
};
ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
touchHelper.attachToRecyclerView(recyclerView);
在我的活动中,这是我删除项目的部分,使用ItemTouchHelper的滑动移动:
07-14 19:34:03.742 5597-5597/bikurim.silverfix.com.bikurim E/AndroidRuntime: FATAL EXCEPTION: main
Process: bikurim.silverfix.com.bikurim, PID: 5597
java.lang.NullPointerException: Attempt to read from field 'long bikurim.silverfix.com.bikurim.models.Family.whenInMillis' on a null object reference
at bikurim.silverfix.com.bikurim.utils.managers.CountDownManager.onTick(CountDownManager.java:73)
at bikurim.silverfix.com.bikurim.utils.managers.CountDownManager$1.handleMessage(CountDownManager.java:105)
at android.os.Handler.dispatchMessage(Handler.java:102)
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)
这是我得到的错误:
{{1}}