Skip to content

Commit

Permalink
Change areItemsTheSame to check if internal objects are the same with…
Browse files Browse the repository at this point in the history
… === (google#1185)

* Call onAnswerChanged Callback instead of questionnaireResponseCHangeCallback

* Remove unnecessary questionnaireResponseItemChangedCallback since onAnswerChanged calls this internally

* questionnaireResponseItem has to be a variable since we clear answers which may contain nested questionnaireReponseItems

* Reverted change from val to var and added override for equals function

* Changed areItemsTheSame to check internal objects

* Added UTs to check the overridden equals function for questionnaireItemViewItem

* Update comments

Co-authored-by: Jing Tang <[email protected]>

* Add new equalsDeep function for questionnaireItemViewItem

* Early return and feedback in code comments

Co-authored-by: Jing Tang <[email protected]>
  • Loading branch information
joiskash and jingtang10 committed Feb 24, 2022
1 parent e6bb4c4 commit f31f5b7
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,10 @@ internal object DiffCallback : DiffUtil.ItemCallback<QuestionnaireItemViewItem>(
override fun areItemsTheSame(
oldItem: QuestionnaireItemViewItem,
newItem: QuestionnaireItemViewItem
) = oldItem.questionnaireItem.linkId == newItem.questionnaireItem.linkId
) = oldItem == newItem

override fun areContentsTheSame(
oldItem: QuestionnaireItemViewItem,
newItem: QuestionnaireItemViewItem
) =
oldItem.questionnaireItem.equalsDeep(newItem.questionnaireItem) &&
oldItem.questionnaireResponseItem.equalsDeep(newItem.questionnaireResponseItem)
) = oldItem.equalsDeep(newItem)
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@ object QuestionnaireItemBarCodeReaderViewHolderFactory :
}

setInitial(questionnaireItemViewItem.singleAnswerOrNull, reScanView)

questionnaireItemViewItem.questionnaireResponseItemChangedCallback()
onAnswerChanged(context)
}
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ internal object QuestionnaireItemDropDownViewHolderFactory :
questionnaireItemViewItem.singleAnswerOrNull =
QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent()
.setValue(questionnaireItemViewItem.answerOption[position].valueCoding)
questionnaireItemViewItem.questionnaireResponseItemChangedCallback()
onAnswerChanged(autoCompleteTextView.context)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,40 @@ data class QuestionnaireItemViewItem(
else -> emptyList()
}
}

/**
* [QuestionnaireItemViewItem] is a transient object for the UI only. Whenever the user makes any
* change via the UI, a new list of [QuestionnaireItemViewItem]s will be created, each holding
* references to the underlying [QuestionnaireItem] and [QuestionnaireResponseItem]. To avoid
* refreshing the UI unnecessarily with the same [QuestionnaireItem]s and
* [QuestionnaireResponseItem]s, we consider two [QuestionnaireItemViewItem]s to be the same if
* they have the same underlying [QuestionnaireItem] and [QuestionnaireResponseItem]. See
* [QuestionnaireItemAdapter.DiffCallback].
*
* On the other hand, under certain circumstances, the underlying [QuestionnaireResponseItem]
* might be recreated for the same question. For example, if a [QuestionnaireItem] is nested under
* another [QuestionnaireItem], the [QuestionnaireResponseItem](s) will be nested under the parent
* [QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent], and if the
* [QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent] is changed, the nested
* [QuestionnaireResponseItem] will be recreated, too. In such cases, it would be incorrect to
* simply check that the `linkId` of the underlying [QuestionnaireItem] and
* [QuestionnaireResponseItem] match.
*/
override fun equals(other: Any?): Boolean {
if (other !is QuestionnaireItemViewItem) return false
return this.questionnaireItem === other.questionnaireItem &&
this.questionnaireResponseItem === other.questionnaireResponseItem
}

/**
* Comparing the contents of two [QuestionnaireItemViewItem]s by traversing the underlying
* [Questionnaire.QuestionnaireItemComponent] and
* [QuestionnaireResponse.QuestionnaireResponseItemComponent] and comparing values of all the
* properties. This is done by using the [Questionnaire.QuestionnaireItemComponent.equalsDeep] and
* [QuestionnaireResponse.QuestionnaireResponseItemComponent.equalsDeep].
*/
fun equalsDeep(other: QuestionnaireItemViewItem): Boolean {
return this.questionnaireItem.equalsDeep(other.questionnaireItem) &&
this.questionnaireResponseItem.equalsDeep(other.questionnaireResponseItem)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ class QuestionnaireItemAdapterTest {
// TODO: test errors thrown for unsupported types

@Test
fun diffCallback_areItemsTheSame_sameLinkId_shouldReturnTrue() {
fun diffCallback_areItemsTheSame_sameLinkIdDifferentObjectId_shouldReturnFalse() {
assertThat(
DiffCallback.areItemsTheSame(
QuestionnaireItemViewItem(
Expand All @@ -360,19 +360,51 @@ class QuestionnaireItemAdapterTest {
) {}
)
)
.isFalse()
}

@Test
fun diffCallback_areItemsTheSame_sameLinkIdSameObjectId_shouldReturnTrue() {
val questionnaireItem =
Questionnaire.QuestionnaireItemComponent().setLinkId("link-id-1").setText("text")
val questionnaireResponseItem = QuestionnaireResponse.QuestionnaireResponseItemComponent()
assertThat(
DiffCallback.areItemsTheSame(
QuestionnaireItemViewItem(questionnaireItem, questionnaireResponseItem) {},
QuestionnaireItemViewItem(questionnaireItem, questionnaireResponseItem) {}
)
)
.isTrue()
}

@Test
fun diffCallback_areItemsTheSame_differentLinkId_shouldReturnFalse() {
val questionnaireResponseItem = QuestionnaireResponse.QuestionnaireResponseItemComponent()
assertThat(
DiffCallback.areItemsTheSame(
QuestionnaireItemViewItem(
Questionnaire.QuestionnaireItemComponent().setLinkId("link-id-1"),
QuestionnaireResponse.QuestionnaireResponseItemComponent()
questionnaireResponseItem
) {},
QuestionnaireItemViewItem(
Questionnaire.QuestionnaireItemComponent().setLinkId("link-id-2"),
questionnaireResponseItem
) {}
)
)
.isFalse()
}

@Test
fun diffCallback_areItemsTheSame_differentQuestionnaireResponseItem_shouldReturnFalse() {
val questionnaireItem =
Questionnaire.QuestionnaireItemComponent().setLinkId("link-id-1").setText("text")
val questionnaireResponseItem = QuestionnaireResponse.QuestionnaireResponseItemComponent()
assertThat(
DiffCallback.areItemsTheSame(
QuestionnaireItemViewItem(questionnaireItem, questionnaireResponseItem) {},
QuestionnaireItemViewItem(
questionnaireItem,
QuestionnaireResponse.QuestionnaireResponseItemComponent()
) {}
)
Expand Down

0 comments on commit f31f5b7

Please sign in to comment.