Это мой фрагмент_дома. xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.home.HomeFragment" >
<TextView
android:id="@+id/bluetooth_connection_status_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_bluetooth_connection_status"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:textSize="20sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/bluetooth_connection_current_status"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.1"
app:layout_constraintStart_toEndOf="@+id/bluetooth_connection_status_label"
app:layout_constraintTop_toTopOf="@+id/bluetooth_connection_status_label" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/toggle_advertising_floating_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="16dp"
android:contentDescription="@string/button"
android:src="@drawable/ic_bluetooth_searching_white_24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.9" />
</androidx.constraintlayout.widget.ConstraintLayout>
Файл HomeViewModel.kt:
class HomeViewModel : ViewModel() {
private val connectionStatus: MutableLiveData<BleConnectionStatus> by lazy { MutableLiveData<BleConnectionStatus>()}
fun setConnectionStatus(value: BleConnectionStatus){
connectionStatus.value = value
Log.d(HomeViewModel::class.java.name, "setConnectionStatus(${connectionStatus.value})")
}
fun getConnectionStatusValue(): MutableLiveData<BleConnectionStatus>{
Log.d(HomeViewModel::class.java.name, "getConnectionStatusValue() :${connectionStatus.value}")
return connectionStatus
}
}
Мой файл HomeViewFragment.kt
class HomeFragment : Fragment() {
private lateinit var homeViewModel: HomeViewModel
private lateinit var connectionStatusTextView: TextView
private lateinit var advertisingFloatingActionButton: FloatingActionButton
private var activityCallback: IToggleAdvertising? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
homeViewModel = ViewModelProvider(this).get(HomeViewModel::class.java)
connectionStatusTextView = root.findViewById(R.id.bluetooth_connection_current_status)
advertisingFloatingActionButton = root.findViewById(R.id.toggle_advertising_floating_button)
return root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
createObserver()
initializeActivityCallback()
advertisingFloatingActionButton.setOnClickListener { toggleAdvertising() }
}
private fun createObserver() {
val connectionStatusObserver = Observer<BleConnectionStatus> {
Log.d(HomeFragment::class.java.name, "Observer updated with $it")
connectionStatusTextView.text = it.toString()
if (it == BleConnectionStatus.SLEEPING) {
advertisingFloatingActionButton.isEnabled = true
advertisingFloatingActionButton.visibility = View.VISIBLE
} else if (it == BleConnectionStatus.ADVERTISING) {
advertisingFloatingActionButton.isEnabled = false
advertisingFloatingActionButton.visibility = View.VISIBLE
} else
advertisingFloatingActionButton.visibility = View.GONE
}
// homeViewModel.getConnectionStatusValue().observe(this, connectionStatusObserver)
homeViewModel.getConnectionStatusValue().observe(viewLifecycleOwner, connectionStatusObserver)
}
private fun initializeActivityCallback() {
try {
activityCallback = context as IToggleAdvertising
} catch (e: ClassCastException) {
e.toString()
}
}
private fun toggleAdvertising(){
Log.d(HomeFragment::class.java.name, "toggleAdvertising() && ${homeViewModel.getConnectionStatusValue().value}")
if(homeViewModel.getConnectionStatusValue().value == BleConnectionStatus.SLEEPING)
activityCallback?.onStartAdvertising()
else if(homeViewModel.getConnectionStatusValue().value == BleConnectionStatus.ADVERTISING)
activityCallback?.onStopAdvertising()
}
override fun onResume() {
super.onResume()
if(homeViewModel.getConnectionStatusValue().value == null)
homeViewModel.setConnectionStatus(BleConnectionStatus.SLEEPING)
}
}
И это мой вывод logcat
2020-04-23 16:09:27.401 17290-17290/? D/MainActivity: checkPermissions()
2020-04-23 16:09:27.446 17290-17290/? D/HomeViewModel: getConnectionStatusValue() :null
2020-04-23 16:09:27.457 17290-17290/? D/MainActivity: initializeBluetooth()
2020-04-23 16:09:27.500 17290-17290/? D/HomeViewModel: getConnectionStatusValue() :null
2020-04-23 16:09:27.500 17290-17290/? D/HomeFragment: Observer updated with Sleeping
2020-04-23 16:09:27.501 17290-17290/? D/HomeViewModel: setConnectionStatus(Sleeping)
2020-04-23 16:09:32.379 17290-17290/ D/HomeViewModel: getConnectionStatusValue() :Sleeping
2020-04-23 16:09:32.379 17290-17290/ D/HomeFragment: toggleAdvertising() && Sleeping
2020-04-23 16:09:32.379 17290-17290/ D/HomeViewModel: getConnectionStatusValue() :Sleeping
2020-04-23 16:09:32.379 17290-17290/ D/MainActivity: onStartAdvertising()
2020-04-23 16:09:32.421 17290-17290/ D/MainActivity: updateBluetoothStatusString(Advertising)
2020-04-23 16:09:32.422 17290-17290/ D/HomeViewModel: setConnectionStatus(Advertising)
2020-04-23 16:12:01.310 17290-17290/ D/HomeViewModel: getConnectionStatusValue() :Sleeping
2020-04-23 16:12:01.310 17290-17290/ D/HomeFragment: toggleAdvertising() && Sleeping
2020-04-23 16:12:01.310 17290-17290/ D/HomeViewModel: getConnectionStatusValue() :Sleeping
2020-04-23 16:12:01.310 17290-17290/ D/MainActivity: onStartAdvertising()
2020-04-23 16:12:01.324 17290-17290/ D/MainActivity: updateBluetoothStatusString(Error)
2020-04-23 16:12:01.324 17290-17290/ D/HomeViewModel: setConnectionStatus(Error)
Я следую инструкциям официального Android сайта и книги "Android Studio 3.2 Основы разработки - Kotlin Edition", но я не обновляю TextView.
Кто-нибудь знает, что я делаю не так? Спасибо заранее.
РЕДАКТИРОВАТЬ: Я обнаружил проблему, Я дважды создал экземпляр класса HomeViewModel : один раз в HomeFragment и один в HomeActivity:
class MainActivity : AppCompatActivity(), IBluetoothStatusUpdater, IToggleAdvertising {
private val TAG = MainActivity::class.java.name
private val REQUEST_ENABLE_BT = 1
private val PERMISSION_REQUEST_FINE_LOCATION = 1
private val PERMISSION_REQUEST_COARSE_LOCATION = 2
private lateinit var mBlePeripheral: BlePeripheral
private lateinit var homeViewModel: HomeViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initializeNavigationComponents()
homeViewModel = ViewModelProvider(this).get(HomeViewModel::class.java)
checkPermissions()
}
...
}
Итак, я хочу обновить GUI HomeFragment и сохранить его статус в HomeViewModel. Обновления MutableLiveData в HomeViewModel поступают из службы Bluetooth, которая должна быть инициализирована в MainActivity.
Итак, мой новый вопрос: должен ли экземпляр HomeViewModel из MainActivity и удалить экземпляр в HomeFragment?
Если нет, какие у меня есть альтернативы? Я рассматриваю репозиторий, но Bluetooth должен быть инициализирован в MainActivity, поэтому я не знаю, как сейчас приступить к дизайну.