EditText का उपयोग करके सरल मानों और data classes को संशोधित करना काफी सीधा है, और आम तौर पर ऐसा दिखता है:

data class Person(var firstName: String, var lastName: Int)

// ...

val (person, setPerson) = remember { mutableStateOf(Person()) }

// common `onChange` function handles both class properties, ensuring maximum code re-use
fun <T> onChange(field: KMutableProperty1<Person, T>, value: T) {
    val nextPerson = person.copy()
    field.set(nextPerson, value)
    setPerson(nextPerson)
}

// text field for first name
TextField(
    value = person.firstName,
    onChange = { it -> onChange(Person::firstName, it) })

// text field for last name name
TextField(
    value = person.lastName,
    onChange = { it -> onChange(Person::lastName, it) })

जैसा कि आप देख सकते हैं, इस उदाहरण में कोड अत्यधिक पुन: प्रयोज्य है: कोटलिन की प्रतिबिंब सुविधाओं के लिए धन्यवाद, हम इस वर्ग में प्रत्येक संपत्ति को संशोधित करने के लिए एक onChange फ़ंक्शन का उपयोग कर सकते हैं।

हालाँकि, एक समस्या तब उत्पन्न होती है जब Person क्लास को स्क्रैच से इंस्टेंट नहीं किया जाता है, बल्कि डिस्क से Room के माध्यम से खींचा जाता है। उदाहरण के लिए, एक PersonDao में एक `findOne() फ़ंक्शन हो सकता है जैसे:

@Query("SELECT * FROM peopleTable WHERE id=:personId LIMIT 1")
fun findOne(personId: String): LiveData<Person>

हालांकि, आप वास्तव में कई कारणों से इस LiveData का remember {} में उपयोग नहीं कर सकते हैं:

  1. जबकि LiveData में observeAsState() नामक एक फ़ंक्शन है, यह State<T> देता है और MutableState<T> नहीं, जिसका अर्थ है कि आप इसे TextFields के साथ संशोधित नहीं कर सकते। इस तरह यह काम नहीं करता है: <उल>
  2. remember { personFromDb.observeAsState()}
  3. आप अपने डेटाबेस से प्राप्त .copy() Person नहीं कर सकते क्योंकि रूम क्वेरी वापस आने से पहले आपका घटक रेंडर हो जाएगा, जिसका अर्थ है कि आप ऐसा नहीं कर सकते, क्योंकि Person क्लास इंस्टेंस को याद रखा जाएगा के रूप में null: <उल>
  4. remember { mutableStateOf(findPersonQueryResult.value) }

यह देखते हुए, इसे संभालने का सही तरीका क्या है? क्या जिस घटक में TextField है, उसे किसी अन्य घटक में लपेटा जाना चाहिए जो कक्ष क्वेरी को संभालता है, और केवल क्वेरी के वापस आने पर ही प्रपत्र प्रदर्शित करता है? LiveData<Person> के इस मामले में यह कैसा दिखेगा?

1
foxtrotuniform6969 23 सितंबर 2020, 15:46

1 उत्तर

सबसे बढ़िया उत्तर

मैं इसे एक प्रति और एक अपरिवर्तनीय डेटा वर्ग के साथ करूँगा

typealias PersonID = Long?
@Entity
data class Person(val firstName: String, val lastName: String) {
    @PrimaryKey(autoGenerate = true)
    val personID: PersonID = null
}
//VM or sth
object VM {
    val liveData: LiveData<Person> = MutableLiveData() // your db call
    val personDao: PersonDao? = null // Pretending it exists
}

@Dao
abstract class PersonDao {
    abstract fun upsert(person: Person)
}

@Composable
fun test() {
    val personState = VM.liveData.observeAsState(Person("", ""))
    TextField(
        value = personState.value.firstName,
        onValueChange = { fName -> VM.personDao?.upsert(personState.value.copy(firstName = fName))}
    )
}
3
2jan222 31 पद 2020, 21:04