显示时间和 notifyDataSetChanged() 时应用程序崩溃

App crashes when showing time and notifyDataSetChanged()

当我使用链接到显示时间的适配器的 notifyDataSetChanged() 为 post 创建新评论时,我的应用程序崩溃了。所有数据都取自 parse.com 我存储所有数据库信息的地方。新发表的评论应该立即显示在显示评论和时间的相同 activity 列表视图中。时间由 createdAt() 减去 currentTime.

错误说:

java.lang.NullPointerException: Attempt to invoke virtual method 'long java.util.Date.getTime()' on a null object reference

这是添加评论的按钮:

                            //Add a new comment
                            mAddComment.setOnClickListener(new View.OnClickListener() {
                                @Override
                                public void onClick(View v) {
                                    Log.d("log", "add button clicked");

                                    final ParseObject myComment = new ParseObject("Comments");
                                    final String comment = mComment.getText().toString();
                                    myComment.put("CommentOwner", currentUserUsername);
                                    myComment.put("Comment", comment);
                                    myComment.put("SocialId", ParseObject.createWithoutData("Social", socialId));
                                    myComment.saveInBackground();

                                    adapter.setNotifyOnChange(false);
                                    adapter.add(myComment);
                                    adapter.notifyDataSetChanged();
                                    setListAdapter(adapter);
                                    if (adapter.isEmpty()) {
                                    } else {
                                        mList.setSelection(mList.getAdapter().getCount() - 1);
                                    }
                                    mComment.setText("");
                                }
                            });

这是适配器内部显示时间的东西:

    public SocialCommentAdapter(Context context, List<ParseObject> Comment) {
        super(context, R.layout.socialcommentcustomlayout, Comment);
            mContext = context;
            mComment = Comment;
    }
    .
    .
    .
    .
    .
    final ParseObject commentObject = mComment.get(position);
    //get Time
    Date created = commentObject.getCreatedAt();
    Date currentDate = new Date();


    long timepast = currentDate.getTime() - created.getTime(); <<<< The Error points to this line of the code

    long days = TimeUnit.MILLISECONDS.toDays(timepast);
    timepast -= TimeUnit.DAYS.toMillis(days);
    long hours = TimeUnit.MILLISECONDS.toHours(timepast);
    timepast -= TimeUnit.HOURS.toMillis(hours);
    long minutes = TimeUnit.MILLISECONDS.toMinutes(timepast);
    timepast -= TimeUnit.MINUTES.toMillis(minutes);
    long seconds = TimeUnit.MILLISECONDS.toSeconds(timepast);

    StringBuilder sb = new StringBuilder(64);
    if( days > 0){
        sb.append(days);
        sb.append("d");
    }else if (hours>0){
        sb.append(hours);
        sb.append("h");
    } else if (minutes >0){
        sb.append(minutes);
        sb.append("m");
    }else if ( seconds >0){
        sb.append(seconds);
        sb.append("s");
    }

    holder.timeComment.setText(sb.toString());

你们知道这有什么问题吗?你们能帮帮我吗?

谢谢

我找到了适合我的解决方案。

我认为问题是创建时间为空。

所以我通过创建一个 if/else 方法解决了这个问题,如下所示:

    //get Time
    Date created = commentObject.getCreatedAt();
    Date currentDate = new Date();
    if( created == null ){
        holder.timeComment.setText("just now");
    }else{

        long timepast = currentDate.getTime() - created.getTime();

        long days = TimeUnit.MILLISECONDS.toDays(timepast);
        timepast -= TimeUnit.DAYS.toMillis(days);
        long hours = TimeUnit.MILLISECONDS.toHours(timepast);
        timepast -= TimeUnit.HOURS.toMillis(hours);
        long minutes = TimeUnit.MILLISECONDS.toMinutes(timepast);
        timepast -= TimeUnit.MINUTES.toMillis(minutes);
        long seconds = TimeUnit.MILLISECONDS.toSeconds(timepast);

        StringBuilder sb = new StringBuilder(64);
        if( days > 0){
            sb.append(days);
            sb.append("d");
        }else if (hours>0){
            sb.append(hours);
            sb.append("h");
        } else if (minutes >0){
            sb.append(minutes);
            sb.append("m");
        }else if ( seconds >0){
            sb.append(seconds);
            sb.append("s");
        }

        holder.timeComment.setText(sb.toString());

    }

这样,如果无法获取创建的时间,它只会说"just now"。这很适合我。

我知道你刚刚回答了你自己的问题,但我正在写我的答案,想添加一个关于为什么你的变量的解释是空的,所以我还是 post 我的答案。

首先,commentObject.getCreatedAt(); 崩溃上方的几行是 returning null,因此您的 created 对象为 null,这就是崩溃的原因。现在进行解释。

Reading the documentation on getCreatedAt(),我们看到return是

的时间

...the creation time will be the time of the first ParseObject.save() call rather than the time the object was created locally.

现在,我们可以看到您已在新 ParseObject 的 onClick 方法中调用了 myComment.saveInBackground();,并将该对象添加到列表中。然后调用 adapter.notifyDataSetChanged(); 触发代码崩溃的 getView 方法。您的 saveInBackground 方法应该保存对象,但是,它将在后台执行...与您在其上创建对象的线程不同的线程。

所以根据我对文档的理解以及我们在这里看到的内容,getCreatedAt() 将 return 为空,直到保存 ParseObject,届时它将 return Date 对象用正确的数据。因为您调用的是 saveInBackground 而不是 save,所以保存发生在后台线程上,这意味着保存可能不会立即发生。执行顺序如下:

  1. 您初始化 ParseObject
  2. 您在对象上调用了 saveInBackground,可能尚未开始保存
  3. 您将对象添加到您的适配器并调用通知
  4. getView 被触发,您的应用程序崩溃,因为日期仍然为空
  5. 也许就在这附近(在某些情况下更早)保存将完成,如果您的应用程序不崩溃,日期将不再为空。

修复它的方法是检查变量是否为空:

if (created != null) {
    long timepast = currentDate.getTime() - created.getTime();
    .
    . // your date forming code here
    .
    holder.timeComment.setText(sb.toString());
} else {
    holder.timeComment.setText("new");
}

希望这有助于解释您获得空对象的原因。