การเชื่อมโยงฐานข้อมูล Android โดยใช้ตัวดำเนินการเชิงตรรกะ“ &&”


133

ฉันพยายามใช้ตัวดำเนินการและ "&&" ใน xml โดยใช้ Android databinding

android:visibility="@{(bean.currentSpaceId == bean.selectedSpaceId **&&** bean.currentSpaceId > 0)? View.VISIBLE: View.GONE}"

แต่ฉันพบข้อผิดพลาดในการคอมไพล์:

ข้อผิดพลาด: การดำเนินการล้มเหลวสำหรับงาน ': app: dataBindingProcessLayoutsDevDebug' org.xml.sax.SAXParseException; systemId: file: /Users/path/app/build/intermediates/res/merged/dev/debug/layout/fragment_space.xml; lineNumber: 106; columnNumber: 89; ชื่อเอนทิตีต้องเป็นไปตาม "&" ในการอ้างอิงเอนทิตีทันที

และข้อผิดพลาดของไฮไลต์สีแดงในสตูดิโอ Android "อักขระที่ไม่ใช้ Escape & หรือไม่มีการสิ้นสุด"

แล้วจะแก้ไขอย่างไรดี?

แก้ไข: พบคำตอบอักขระเหล่านี้จำเป็นต้องหลีกเลี่ยง:

'&' --> '&'

'<' --> '&lt;'

'>' --> '&gt;'

ฉันสังเกตเห็นว่าฉันสามารถใช้ ">" และ "<" ในไฟล์ xml เลย์เอาต์ได้
Hong

คำตอบ:


235

&&&amp;&amp;ควรจะแสดงผลเป็น

คู่มือการผูกข้อมูลอย่างเป็นทางการมีตัวอย่างของตัวดำเนินการเปรียบเทียบที่ใช้เอนทิตี XML เหล่านี้เป็นต้น

android:visibility="@{age &lt; 13 ? View.GONE : View.VISIBLE}"

แก้ไข

ตัวอย่างสำนวนที่ฉันพูดถึงในคำตอบหายไปจากเอกสารฉบับภาษาอังกฤษเนื่องจากคำตอบนี้ถูกเขียนขึ้น พวกเขาสามารถอยู่รอดได้ในเอกสารเวอร์ชันเก่าที่ไม่ใช่ภาษาอังกฤษเช่นเวอร์ชันภาษาสเปน

ไม่ว่าจะด้วยวิธีใดคำตอบเดิมก็ยังคงใช้ได้เนื่องจากการใช้เอนทิตี XML ใน XML เป็นมาตรฐานใน XML และไม่มีส่วนเกี่ยวข้องกับ Android


12
อย่าใช้ลอจิกของโดเมนในนิพจน์การผูกคุณมีตัวกำหนด / ตัวควบคุมสำหรับสิ่งนี้
artkoenig

2
@ ArtjomKönigแล้วถ้าคุณต้องซ่อน / แสดงการควบคุมบางอย่างใน UI? ฉันใช้ไลบรารีการผูกข้อมูลเพื่อไม่เขียนโค้ด UI
Krusty

3
@Krusty เสริมเมธอด isMyControlVisible () ในผู้นำเสนอของคุณซึ่งคุณใช้ตรรกะของโดเมนเพื่อส่งกลับจริงหรือเท็จ ผูกกับวิธีนี้
artkoenig

1
ฉันคิดว่าหากคุณมีตัวแปรบูลีนมากเกินไปการแก้ปัญหานี้ก็ใช้ได้ ไม่งั้นโค้ดของคุณจะมี ObservableBoolean.set มากมาย
Lester

@artkoenig คุณจะต้องรักษาบูลีนพิเศษเหล่านั้นไว้ทุกที่ที่คุณอ้างอิงถึงเค้าโครง แหล่งที่มาของจุดบกพร่อง
Ali Kazi

37

รายการเอนทิตี HTML

คุณไม่สามารถใช้&หรือเอนทิตี HTMLอื่น ๆใน XML ได้ ดังนั้นคุณต้องใช้อักขระหลีก

android:text="@{(1==1 &amp;&amp; 2>0) ? `true` : `false`}"

เอนทิตีอักขระ HTML มักใช้ใน Android:

+--------+----------------------------+--+--+--+
| Symbol | Equivalent HTML Entity     |  |  |  |
+--------+----------------------------+--+--+--+
| >      | &gt;                       |  |  |  |
+--------+----------------------------+--+--+--+
| <      | &lt;                       |  |  |  |
+--------+----------------------------+--+--+--+
| "      | &quot;, &ldquo; or &rdquo; |  |  |  |
+--------+----------------------------+--+--+--+
| '      | &apos;, &lsquo; or &rsquo; |  |  |  |
+--------+----------------------------+--+--+--+
| }      | &#125;                     |  |  |  |
+--------+----------------------------+--+--+--+
| &      | &amp;                      |  |  |  |
+--------+----------------------------+--+--+--+
| space  | &#160;                     |  |  |  |
+--------+----------------------------+--+--+--+

นี่คือรายการเอนทิตี HTML ทั้งหมด


18

การหลีกเลี่ยง && ในการมาร์กอัปเค้าโครงเป็นวิธีแก้ปัญหาที่ไม่ดีมาก จะเป็นการดีกว่าที่จะสร้างเมธอดบนวัตถุโมเดล (ดู):

android:visibility="@{user.adult ? View.VISIBLE : View.GONE}"

public boolean isAdult() {
    return age >= 18;
}

4
แม้ว่านี่จะเป็นวิธีแก้ปัญหาที่ดี แต่น่าเสียดายที่ไม่ได้รับการเรียกเมื่อค่าตัวแปรเปลี่ยนไป (alertPropertyChanged) และการเปิดเผยจะไม่ถูกอัปเดต
Bernd Kampl

3
@BerndKampl UseObservableBoolean isAdult
S1ngoooor

มันจะไม่ได้ผลมันจะถูกเรียกเพียงครั้งเดียว!
CodingTT

@BerndKampl ใช้ยังไงก็ยังโดนเรียกครั้งเดียว
CodingTT

@CodingTT ดูคำตอบของฉันคุณจะต้องมีการโทร alertPropertyChanged ที่ไหนสักแห่งเพื่ออัปเดต
Bernd Kampl

3

ทางออกที่ดีที่สุดที่ฉันสามารถหาได้สำหรับปัญหานี้คือการแนะนำวิธีการ Bindable ใหม่

ก่อน:

item_recyclerview.xml:

<EditText
...
android:enabled="@{myViewModel.myDataModelClass.lastAddedItem &amp;&amp; !myViewModel.myDataModelClass.editTextDisabled}"
/>

MyDataModelClass:( ซึ่งจัดขึ้นในโมเดลมุมมองของฉัน)

...
private boolean lastAddedItem;
private boolean editTextDisabled;
...
@Bindable
public boolean isLastAddedItem() {
    return lastAddedItem;
}
public void setLastAddedItem(boolean lastAddedItem) {
    this.lastAddeditem = lastAddedItem;
    notifyPropertyChanged(BR.lastAddedItem);
}
@Bindable
public boolean isEditTextDisabled() {
    return editTextDisabled;
}
public void setEditTextDisabled(boolean editTextDisabled) {
    this.editTextDisabled = editTextDisabled;
    notifyPropertyChanged(BR.editTextDisabled);
}

หลังจาก:

item_recyclerview.xml:

<EditText
...
android:enabled="@{myViewModel.myDataModelClass.enableEditing}"
/>

MyDataModelClass:( ซึ่งจัดขึ้นในโมเดลมุมมองของฉัน)

...
private boolean lastAddedItem;
private boolean editTextDisabled;
...
@Bindable
public boolean isLastAddedItem() {
    return lastAddedItem;
}
public void setLastAddedItem(boolean lastAddedItem) {
    this.lastAddeditem = lastAddedItem;
    notifyPropertyChanged(BR.lastAddedItem);
    notifyPropertyChanged(BR.isEnableEditing);
}
@Bindable
public boolean isEditTextDisabled() {
    return editTextDisabled;
}
public void setEditTextDisabled(boolean editTextDisabled) {
    this.editTextDisabled = editTextDisabled;
    notifyPropertyChanged(BR.editTextDisabled);
    notifyPropertyChanged(BR.isEnableEditing);
}
@Bindable
public boolean isEnableEditing() {
    return isLastAddedItem() && !isEditTextDisabled();
}

รหัสนั้นใช้คลาส BaseObservable BR คือคลาสการผูกที่สร้างขึ้น ดูโพสต์นี้สำหรับคำอธิบายโดยละเอียดเพิ่มเติม: medium.com/@jencisov/…
Bernd Kampl
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.