![](/img/trans.png)
[英]How can i clear text of selected Place name from AutocompleteSupportFragment?
[英]How can a ViewModel function access the Place instance returned by PlaceSelectionListener of AutocompleteSupportFragment?
我正在使用 Kotlin 構建一個 Android 應用程序。
我有一個包含create_button的布局。 當用戶單擊按鈕時, onClick應該在我的 ViewModel 中調用onCreateJourney()
。 此 function 需要selectedPlaceId
參數來更新 Journey 實體的值。
在我的 Fragment 中,我使用 AutocompleteSupportFragment 讓用戶搜索並選擇所需的位置。 這很好用,因為onPlaceSelected()
返回正確的位置以響應用戶的選擇。 但我無法弄清楚如何在我的 ViewModel onCreateJourney()
。
在這個階段,編譯器會拋出這個錯誤:
在 class com.example.traveljournal.journey.NewJourneyViewModel 中找不到方法 onCreateJourney()
拜托,你能為我解釋一下這個問題嗎?
我的用戶界面(.xml 片段布局):
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".journey.NewJourneyFragment">
<data>
<variable
name="newJourneyViewModel"
type="com.example.traveljournal.journey.NewJourneyViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/whereQuestion"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="10dp"
android:text="@string/whereQuestion"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.027"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/journeyBckgImageView" />
<androidx.cardview.widget.CardView
android:id="@+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent">
</androidx.cardview.widget.CardView>
<fragment
android:id="@+id/autocomplete_fragment"
android:name="com.google.android.libraries.places.widget.AutocompleteSupportFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/whereQuestion" />
<Button
android:id="@+id/create_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:onClick="@{() -> newJourneyViewModel.onCreateJourney()}"
android:text="@string/createJourneyButton"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
我的視圖模型
class NewJourneyViewModel (
private val journeyKey: Long = 0L,
val database: TravelDatabaseDao) : ViewModel() {
private var viewModelJob = Job()
private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
private val _navigateToJourneys = MutableLiveData<Boolean?>()
val navigateToJourneys: LiveData<Boolean?>
get() = _navigateToJourneys
fun doneNavigating() {
_navigateToJourneys.value = null
}
fun onCreateJourney(selectedPlaceId: String) {
uiScope.launch {
withContext(Dispatchers.IO) {
val journey = database.getJourney(journeyKey) ?: return@withContext
journey.placeId = selectedPlaceId
database.updateJourney(journey)
}
_navigateToJourneys.value = true
}
}
override fun onCleared() {
super.onCleared()
viewModelJob.cancel()
}
}
我的片段
class NewJourneyFragment : Fragment(), PlaceSelectionListener {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
(activity as AppCompatActivity).supportActionBar?.title = getString(R.string.createJourney)
val binding: FragmentNewJourneyBinding = DataBindingUtil.inflate(
inflater,
R.layout.fragment_new_journey, container, false
)
val application = requireNotNull(this.activity).application
val arguments = NewJourneyFragmentArgs.fromBundle(arguments!!)
val dataSource = TravelDatabase.getInstance(application).travelDatabaseDao
val viewModelFactory = NewJourneyViewModelFactory(arguments.journeyKey, dataSource)
val newJourneyViewModel =
ViewModelProviders.of(
this, viewModelFactory).get(NewJourneyViewModel::class.java)
binding.newJourneyViewModel = newJourneyViewModel
newJourneyViewModel.navigateToJourneys.observe(this, Observer {
if(it == true) {
this.findNavController().navigate(
NewJourneyFragmentDirections.actionNewJourneyDestinationToJourneysDestination())
newJourneyViewModel.doneNavigating()
}
})
if (!Places.isInitialized()) {
this.context?.let { Places.initialize(it, getString(R.string.apiKey), Locale.US) }
}
val autocompleteFragment = childFragmentManager.findFragmentById(R.id.autocomplete_fragment)
as? AutocompleteSupportFragment
autocompleteFragment?.setOnPlaceSelectedListener(this)
autocompleteFragment!!.setHint(getString(R.string.destinationExample))
autocompleteFragment!!.setPlaceFields(Arrays.asList(Place.Field.ID, Place.Field.NAME))
return binding.root
}
@ExperimentalStdlibApi
override fun onPlaceSelected(p0: Place) {
Log.i("PLACE", "Place: " + p0.name + ", " + p0.id)
}
override fun onError(status: Status) {
Toast.makeText(this.context,""+status.toString(),Toast.LENGTH_LONG).show()
Log.i("ERROR", "An error occurred: " + status)
}
}
您必須將字段selectedPlaceId
作為參數傳遞給 xml:
android:onClick="@{() -> newJourneyViewModel.onCreateJourney(newJourneyViewModel.selectedPlaceId)}"
您將如何獲得視圖 model 中的 selectedPlaceId 取決於您的編程邏輯。
出於測試目的,您可以對值進行硬編碼。
在 NewJourneyViewModel 中,我將selectedPlaceId
設置為 MutableLiveData。
val selectedPlaceId = MutableLiveData<String>()
在 NewJourneyFragment 中,我使用lateinit
為 NewJourneyViewModel 創建了一個名為newJourneyViewModel
的字段,並在onCreateView()
中對其進行了初始化。
private lateinit var newJourneyViewModel : NewJourneyViewModel
現在可以在onCreateView()
之外訪問我的 ViewModel,在我的 Fragment onPlaceSelected()
方法中,我可以將selectedPlaceId
的值設置為p0.id
。
newJourneyViewModel.selectedPlaceId.value = p0.id
如果有人能對此提出更好、更安全的方法,將不勝感激。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.