2016-08-28 10 views
0

私がしたいのは、フィード内のCommentオブジェクトの「好き」の値をインクリメントして、アイテムが変更されたことをアダプタに通知することです。期待される振る舞いは、以下の通りでなければなりません。1)ユーザーはコメント、2)ListViewの更新がコメントの新しい値で好きです。 this.adapter.add(mComments.get(position - 1));を設定すると、前のコメントに置き換えられます。 this.adapter.add(mComments.get(position)を使用するとアプリがクラッシュします。これを行う方法はありますか?あなたが本当にそれを戻すことはできません削除されたので、私は推測する... RecyclerAdapterにアップグレードし、notifyItemChanged(int position)を呼び出す以外に、代替ですか?ListViewのリストアイテムを即座に更新するには?

public class CommentAdapter extends ArrayAdapter<ParseObject> { 

    protected Context mContext; 
    protected List<ParseObject> mComments; 
    private CommentAdapter adapter; 

    ImageLoader profilePictureImageLoader; 

    public CommentAdapter(Context context, List<ParseObject> comments) { 
     super(context, R.layout.comment_listview_item, comments); 
     mContext = context; 
     mComments= comments; 
     this.adapter = this; 

     profilePictureImageLoader = new ImageLoader(new ProfilePictureFileCache(mContext)); 
    } 

@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    ViewHolder holder; 

holder.likeImage.setOnClickListener(v -> { 
    v.startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.image_click)); 
    createLike(position); 
}); 

    return convertView; 
} 

機能は以下のとおりです。

private void createLike(int position) { 

     ParseQuery<ParseObject> query = new ParseQuery<>(ParseConstants.CLASS_COMMENT); 
     query.whereEqualTo(ParseConstants.KEY_OBJECT_ID, getItem(position).getObjectId()); 
     query.findInBackground((comment, e) -> { 
      // Find the single Comment object associated with the current ListAdapter position 
      if (e == null) for (ParseObject commentObject : comment) { 

       // Create a list to store the likers of this Comment 
       List<String> likedBy = commentObject.getList("likedBy"); 
       System.out.println(likedBy); 

       // If you are not on that list, then create a Like 
       if (!(likedBy.contains(ParseUser.getCurrentUser().getObjectId()))) { 

        // Create new Like object 
        ParseObject newLike2 = new ParseObject(ParseConstants.CLASS_LIKE); 
        newLike2.put(ParseConstants.KEY_SENDER_ID, ParseUser.getCurrentUser()); 
        newLike2.put(ParseConstants.KEY_COMMENT_OBJECT_ID, commentObject); 
        Toast.makeText(getContext(), "Comment liked", Toast.LENGTH_SHORT).show(); 
        newLike2.saveInBackground(); 

        // Add unique User objectId to likedBy array in Parse 
        commentObject.addAllUnique("likedBy", Collections.singletonList(ParseUser.getCurrentUser().getObjectId())); 
        commentObject.saveInBackground(); 

        // Increment the likeCount in the Comment feed 
        incrementLikeCount(commentObject, position); 

        // Initiate Like notification 
        handleLikeNotification(query, commentObject); 

       } else { 
        Toast.makeText(getContext(), "You already liked this Comment", Toast.LENGTH_SHORT).show(); 
       } 

      } 
      else { 
       Log.e("Error", e.getMessage()); 
      } 
     }); 

    } 

private void incrementLikeCount(ParseObject commentObject, int position); 

    // Increment likeCount on related Comment object 
    commentObject.increment("likeCount"); 
    commentObject.saveInBackground(); 

    this.adapter.remove(mComments.get(position)); 
    this.adapter.add(mComments.get(position)); 
    this.adapter.notifyDataSetChanged(); 

    } 

私は、次の例外を取得:

08-28 22:46:04.359 28894-28894/com.yitter.android E/AndroidRuntime: FATAL EXCEPTION: main 
    Process: com.yitter.android, PID: 28894 
    java.lang.IndexOutOfBoundsException: Invalid index 3, size is 2 
     at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255) 
     at java.util.ArrayList.get(ArrayList.java:308) 
     at com.yitter.comment.CommentAdapter.lambda$incrementLikeCount$33(CommentAdapter.java:260) 
     at com.yitter.comment.CommentAdapter.access$lambda$6(CommentAdapter.java:0) 
     at com.yitter.comment.CommentAdapter$$Lambda$9.done(Unknown Source) 
     at com.parse.ParseTaskUtils$2$1.run(ParseTaskUtils.java:116) 
     at android.os.Handler.handleCallback(Handler.java:739) 
     at android.os.Handler.dispatchMessage(Handler.java:95) 
     at android.os.Looper.loop(Looper.java:148) 
     at android.app.ActivityThread.main(ActivityThread.java:5417) 
     at java.lang.reflect.Method.invoke(Native Method) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
+1

これは単なる推測です。私は 'mComments'はアダプタで使われているものと同じリストへの参照だと思います。その場合、 'this.adapter.remove(mComments.get(position))'は 'mComments'から要素を削除し、そのサイズを減らします。 – Titus

+0

その前提はおそらく正しいでしょう。アイテムはもはや存在しないので、アイテムを元に戻すことはできません。アイテムを即座に変更できるようにListViewでこれを回避する方法はありますか? – santafebound

+0

その場合は、アイテムを追加したり削除したりする必要はありません。アダプタを更新するだけで、変更が表示されます。 – Titus

答えて

0

はこれを試してみてください:

private void incrementLikeCount(ParseObject commentObject, int position); 
    commentObject.increment("likeCount"); 
    mComments.get(position).increment("likeCount"); 
    this.adapter.notifyDataSetChanged();  
    commentObject.saveInBackground(); 
} 

あるいは、commentObjectは、より多くの変更をインクリメントlikeCountを持っている場合、あなたはこれを行うことができます。

private void incrementLikeCount(ParseObject commentObject, int position); 
    commentObject.increment("likeCount"); 
    this.adapter.remove(position); 
    this.adapter.add(commentObject); 
    this.adapter.notifyDataSetChanged();  
    commentObject.saveInBackground(); 
} 
+0

これはうまくいった!オブジェクトを保存する前に '' notifyDataSetChanged''を実行するのはなぜですか? – santafebound

+0

@bluemunchローカルオブジェクト 'mComments.get(position)'はすでに変更されており、クラウドオブジェクトを更新するだけで、GUIをリフレッシュするために待つ必要はありません。 – Titus

+0

非常によく知っています。ありがとう! – santafebound

1

[OK]を、私はあなたの問題を解決する方法を知っています。

これは、コードのあなたの部分である:、

private void incrementLikeCount(ParseObject commentObject, int position); 

    // Increment likeCount on related Comment object 
    commentObject.increment("likeCount"); 
    commentObject.saveInBackground(); 

    this.adapter.remove(mComments.get(position)); 
    this.adapter.add(mComments.get(position)); 
    this.adapter.notifyDataSetChanged(); 

} 

見て、リストのサイズがある場合は4に等しく、そしてあなたが3(リストの最後の要素)に等しいpositionの値でincrementLikeCountを呼び出しますアプリがクラッシュします。最初にリストのオブジェクトを削除します(したがって、そのサイズは3になります(最後のインデックス位置は2になります)。同じposition値(=3)を渡して同じ要素をリストから取得しようとした後。限り、最後のインデックスは、今あるよう2に等しく、そしてあなたは、インデックス3にある要素を取得しようとしている、アプリがクラッシュします

これにコードを変更することを検討:。

private void incrementLikeCount(ParseObject commentObject, int position); 

    // Increment likeCount on related Comment object 
    commentObject.increment("likeCount"); 
    commentObject.saveInBackground(); 

    this.adapter.remove(commentObject); 
    this.adapter.add(commentObject); 
    this.adapter.notifyDataSetChanged(); 

} 

しかし、見て、あなたは削除して、同じオブジェクトをリストに追加しています!!!あなたはオブジェクトとコールを更新するだけですthis.adapter.notifyDataSetChanged();

private void incrementLikeCount(ParseObject commentObject, int position); 

    // Increment likeCount on related Comment object 
    commentObject.increment("likeCount"); 
    commentObject.saveInBackground(); 

    this.adapter.notifyDataSetChanged(); 

} 
+0

私は元のmCommentsのリストから位置を得ています。 – santafebound

+0

私たちがあなたを助けることができるように、問題に関わるコード全体を投稿してもらえますか?乾杯。 –

+0

はい、私が更新しました。ありがとう! – santafebound

1

ビューを追加/削除する必要はありません。

あなたは代わりに(あなたは、各行にコメントオブジェクトを持っている場合、私は仮定し、そのカウント「のような」と)あなたのモデルを更新し()notifydatasetchanged呼び出す必要があります。あなただけではなく、それらのすべての1つの項目に()notifyitemchangedを呼び出すことができるように

はまた、あなたはおそらくRecycleViewを使用して更新する必要があり、これは、彼らはそれを作成した理由の一つです。

+0

notifydatasetchanged()だけではアイテムを更新していないようです。 – santafebound

関連する問題