Транзакция не обновляет свойство в Android FireStore - PullRequest
0 голосов
/ 31 августа 2018

Я пытаюсь добавить функцию, которая нравится или не нравится в моем сообщении (вопрос). Но это не обновляет подобное изображение кнопки.

public class QuestionDetailActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "QuestionDetailActivity";
    private Context mContext;
    private TextView questionTitleTv;
    private RadioGroup radioLL;
    private EditText answerEt;
    private LinearLayout checkboxLL;
    private LinearLayout commentLL;

    private FirebaseFirestore db = null;
    private String questionID;

    private String userID;
    private TextView likeCountTv,favouriteCountTv;
    private boolean isLikedByUser = false,isFavouriteByUser = false;
    private DocumentReference questionRef;
    private QuestionBO questionBO;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_question_detail);

        mContext = QuestionDetailActivity.this;
        db = FirebaseFirestore.getInstance();

        userID = "V5BUeBFYR8WKOQUiBFxKrfMHK8Y2";

        questionTitleTv = findViewById(R.id.tv_question_title);
        radioLL = findViewById(R.id.ll_radio);
        answerEt = findViewById(R.id.et_answer);
        checkboxLL = findViewById(R.id.ll_checkbox);
        commentLL = findViewById(R.id.ll_comments);

        likeCountTv = findViewById(R.id.tv_like_count);
        favouriteCountTv = findViewById(R.id.tv_favourite_count);

        likeCountTv.setOnClickListener(this);
        favouriteCountTv.setOnClickListener(this);

        if (getIntent() != null) {
            questionID = getIntent().getExtras().getString("keyQuestionID", "");
        }
        questionRef = db.collection("questionCollection").document(questionID);
        if (!questionID.isEmpty()) {
            getQuestionDetail();
            ///showComments();
            updateFavouriteAndLikeIcons();
        }
    }

    private void updateFavouriteAndLikeIcons() {

        questionRef.collection("favouriteCollection").document(userID).get()
                .addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
                    @Override
                    public void onSuccess(DocumentSnapshot documentSnapshot) {
                        if(documentSnapshot.exists()){
                            isFavouriteByUser = true;
                            // and make it blue
                            Drawable image = getResources().getDrawable( R.drawable.icn_fav_yes );
                            int h = image.getIntrinsicHeight();
                            int w = image.getIntrinsicWidth();
                            image.setBounds( 0, 0, w, h );
                            favouriteCountTv.setCompoundDrawables( image, null, null, null );
                        }
                    }
                });

        questionRef.collection("likeCollection").document(userID).get()
                .addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
                    @Override
                    public void onSuccess(DocumentSnapshot documentSnapshot) {
                        if(documentSnapshot.exists()){
                            boolean isLiked = documentSnapshot.getBoolean(userID);
                            if(isLiked){
                                isLikedByUser = true;
                                // and make it blue
                                Drawable image = getResources().getDrawable( R.drawable.icn_like_yes );
                                int h = image.getIntrinsicHeight();
                                int w = image.getIntrinsicWidth();
                                image.setBounds( 0, 0, w, h );
                                likeCountTv.setCompoundDrawables( image, null, null, null );
                            }
                            else{//dislike
                            }
                        }
                    }
                });

    }

    private void showComments() {
        db.collection("commentCollection").whereEqualTo("questionID", questionID)
                .get()
                .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                    @Override
                    public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                        if (queryDocumentSnapshots.isEmpty()) {
                            Log.d(TAG, "onSuccess: LIST EMPTY");
                            return;
                        } else {
                            // Convert the whole Query Snapshot to a list
                            // of objects directly! No need to fetch each
                            // document.
                            List<CommentBO> commentList = queryDocumentSnapshots.toObjects(CommentBO.class);

                            if (commentList != null && commentList.size() > 0) {
                                for (int x = 0; x < commentList.size(); x++) {
                                    try {
                                        LinearLayout.LayoutParams childParam = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                                                LinearLayout.LayoutParams.WRAP_CONTENT);

                                        childParam.setMargins(20, 10, 0, 0);
                                        View commentByView = LayoutInflater.from(mContext).inflate(R.layout.item_comment, null);
                                        TextView tvCommenter = (TextView) commentByView.findViewById(R.id.item_tv_commenter_name);
                                        TextView tvCommenterComment = (TextView) commentByView.findViewById(R.id.item_tv_commenter_comment);
                                        TextView tvCommentDate = (TextView) commentByView.findViewById(R.id.item_tv_comment_date);

                                        tvCommenter.setText(commentList.get(x).getCommentedBy());
                                        tvCommenterComment.setText(commentList.get(x).getComment());

                                        ///tvCommentDate.setText();
                                        commentLL.addView(commentByView, childParam);

                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
                        }
                    }
                });
    }

    private void getQuestionDetail() {
        questionRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
            @Override
            public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                if (task.isSuccessful()) {
                    DocumentSnapshot document = task.getResult();
                    if (document.exists()) {
                        Log.d(TAG, "DocumentSnapshot data: " + document.getData());
                        questionBO = document.toObject(QuestionBO.class);
                        updateView(questionBO);
                    } else {
                        Log.d(TAG, "No such document");
                    }
                } else {
                    Log.d(TAG, "get failed with ", task.getException());
                }
            }
        });
    }

    private void updateView(QuestionBO mQuestionBO) {
        if (mQuestionBO != null) {
            questionTitleTv.setText(mQuestionBO.getTitle());

            likeCountTv.setText(mQuestionBO.getTotalLikes() + "");
            favouriteCountTv.setText(mQuestionBO.getTotalFavourites() + "");

            switch (mQuestionBO.getQuestionType()) {
                case CHECKBOX:
                    checkboxLL.setVisibility(View.VISIBLE);
                    if (mQuestionBO.getOptions() != null && mQuestionBO.getOptions().size() > 0) {
                        checkboxLL.removeAllViews();

                        for (int x = 0; x < mQuestionBO.getOptions().size(); x++) {
                            final CheckBox subCheckbox = new CheckBox(mContext);
                            subCheckbox.setText(mQuestionBO.getOptions().get(x));
                            subCheckbox.setOnClickListener(new View.OnClickListener() {
                                @Override
                                public void onClick(View view) {

                                }
                            });

                            checkboxLL.addView(subCheckbox, new LinearLayout.LayoutParams(
                                    LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
                        }
                    }
                    break;
                case RADIO:
                    radioLL.setVisibility(View.VISIBLE);
                    if (mQuestionBO.getOptions() != null && mQuestionBO.getOptions().size() > 0) {
                        radioLL.removeAllViews();

                        for (int x = 0; x < mQuestionBO.getOptions().size(); x++) {

                            final RadioButton subRadio = new RadioButton(mContext);
                            subRadio.setText(mQuestionBO.getOptions().get(x));
                            radioLL.addView(subRadio, new LinearLayout.LayoutParams(
                                    LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
                        }
                    }
                    break;
                case DESCRIPTIVE:
                    answerEt.setVisibility(View.VISIBLE);
                    break;
            }
        }
    }

    private void likeOrDislikeThisQuestion(){

        final Task<Boolean> booleanTask = db.runTransaction(new Transaction.Function<Boolean>() {

            @Nullable
            @Override
            public Boolean apply(@NonNull Transaction transaction) throws FirebaseFirestoreException {
                DocumentReference likeRef = questionRef.collection("likeCollection")
                        .document(userID);
                Map<String,Object> map = new HashMap<>();
                 DocumentSnapshot snapshot = transaction.get(likeRef);
                 if(snapshot.exists()){ // it means this is a favourite question of this user.
                     if(snapshot.getBoolean(questionID) && isLikedByUser){
                         isLikedByUser = false;
                         map.put(questionID,isLikedByUser);
                         transaction.update(likeRef,map);
                         int numberOfLikes = questionBO.getTotalLikes();
                         transaction.update(questionRef,"totalLikes",--numberOfLikes);
                         likeCountTv.setText(numberOfLikes + "");
                         return isLikedByUser;
                     }
                     else if(!snapshot.getBoolean(questionID) && !isLikedByUser){
                         isLikedByUser = true;
                         map.put(questionID,isLikedByUser);
                         transaction.update(likeRef,map);
                         int numberOfLikes = questionBO.getTotalLikes();
                         transaction.update(questionRef,"totalLikes",-++numberOfLikes);
                         likeCountTv.setText(numberOfLikes + "");
                         return isLikedByUser;
                     }
                 }
                 else {
                     isLikedByUser = !isLikedByUser;
                     map.put(questionID,isLikedByUser);// pass oposite of it..
                     transaction.set(likeRef,map);

                     int numberOfLikes = questionBO.getTotalLikes();
                     if(isLikedByUser)
                         ++numberOfLikes;
                     else
                         --numberOfLikes;
                     transaction.update(questionRef,"totalLikes",numberOfLikes);

                     likeCountTv.setText(numberOfLikes + "");
                     return isLikedByUser;
                 }
                return null;
            }
        });

        booleanTask.addOnSuccessListener(new OnSuccessListener<Boolean>() {
            @Override
            public void onSuccess(Boolean isLiked) {
                if(isLiked == null){

                }
                else if(isLiked){
                    Drawable image = getResources().getDrawable( R.drawable.icn_like_yes );
                    int h = image.getIntrinsicHeight();
                    int w = image.getIntrinsicWidth();
                    image.setBounds( 0, 0, w, h );
                    likeCountTv.setCompoundDrawables( image, null, null, null );
                }
                else{
                    Drawable image = getResources().getDrawable( R.drawable.icn_like_no );
                    int h = image.getIntrinsicHeight();
                    int w = image.getIntrinsicWidth();
                    image.setBounds( 0, 0, w, h );
                    likeCountTv.setCompoundDrawables( image, null, null, null );
                }
            }
        });
    }

    private void favouriteOrDisFavouriteQuestion(){

    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.tv_like_count:
                likeOrDislikeThisQuestion();
                break;
            case R.id.tv_favourite_count:
                break;
        }
    }
}

Я обновил значок, используя updateFavouriteAndLikeIcons() в первый раз. затем, когда пользователь нажимает кнопку «Мне нравится», я звонил likeOrDislikeThisQuestion(). Обновление счетчика, но оставлено для рисования без обновления. и иногда переменная isLikedByUser становится ложной.

Если вопрос уже понравился, то LikeCollection должен иметь этот документ. если этот документ не существует, это означает, что пользователю это не понравилось или не понравилось.

Моя архитектура базы данных похожа на

 - likeCollection
      userID (Document ID)
         questionID = true // true for like and false for dislike..

1 Ответ

0 голосов
/ 31 августа 2018

От Документы Firebase :

Не изменяйте состояние приложения внутри функций транзакции. Это создаст проблемы параллелизма, потому что функции транзакций могут выполняться несколько раз и не гарантированно будут выполняться в потоке пользовательского интерфейса. Вместо этого передавайте нужную информацию из функций транзакций.

Это то, что происходит здесь, вы должны запускать все модификации приложения внутри слушателя для вашей переменной booleanTask. Не изменяйте переменную класса в методе транзакции apply.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...