Я работаю над школьным проектом, и у меня началось странное поведение в комнате.Я должен признать, что все раньше работало корректно , но после изменения некоторых вещей он остановился, и теперь он не работает, хотя я вернул почти все туда, где он был.
Вот мой UserDao.kt:
@Dao
interface UserDao {
@Query("SELECT * FROM $USER_TABLE_NAME")
fun getAll(): LiveData<List<User>>
@Query("SELECT * FROM $USER_TABLE_NAME WHERE id = :id")
fun getById(id: Int): LiveData<User>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(user: User)
@Update
fun update(user: User)
@Query("UPDATE $USER_TABLE_NAME SET pictureAddress = :image WHERE id = :id")
fun updateImageWhereId(id: Int, image: String)
@Delete
fun delete(user: User)
}
Вот LoginFragment.kt, первый фрагмент, который загружается при запуске приложения.Здесь я проверяю, есть ли пользователь в базе данных, и, если он есть, я проверяю, совпадают ли пароли. Это место, где запрос возвращает пользователя, которого он должен был вернуть, и все работает.
class LoginFragment : Fragment() {
private lateinit var binding: FragmentLoginBinding
private lateinit var model: MainViewModel
private val navigation: INavigationCallback by lazy {
activity as INavigationCallback
}
data class IdPassword(var id: String = "", var password: String = "", var isCorrect: Boolean = true)
private val idPassword: IdPassword = IdPassword()
override fun onCreateView(inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?): View? =
DataBindingUtil.inflate<FragmentLoginBinding>(inflater,
R.layout.fragment_login,
container, false).run {
binding = this
model = activity!!.let {
ViewModelProviders
.of(it, MainViewModel.Factory(it.application))
.get(MainViewModel::class.java)
}
lifecycleOwner = this@LoginFragment
idPassword = this@LoginFragment.idPassword
navigation = this@LoginFragment.navigation
applyLoginButton.setOnClickListener { tryLogin() }
return root
}
private fun tryLogin() {
//databaseData.getUserById - is basically a wrapper
model.databaseData.getUserById(idPassword.id.toInt()).observe(activity!!, Observer {
if(it != null && it.password == idPassword.password){
model.activeUserId = it.id //this stores active user's id
navigation.navigateTo(R.id.action_loginFragment_to_mainMenuFragment)
} else {
binding.errorLogin.visibility = View.VISIBLE
}
})
}
}
После успешного входа мы попадаем на экран главного меню, гдеМне нужно еще раз, чтобы получить пользователя, чтобы отобразить его имя и фотографию профиля.Вот MainMenuFragment.kt , место, где тот же запрос, что и выше, возвращает ноль.Я также попытался проверить это, поэтому прочитайте комментарии, чтобы лучше понять, что я сделал:
class MainMenuFragment : Fragment() {
private lateinit var binding: FragmentMainMenuBinding
private val viewEffect: MainMenuViewUtils by lazy {
MainMenuViewUtils(binding.userNameSmall, binding.mainLinearLayoutTitle)
}
private val globalLayoutListener = object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
binding.root.viewTreeObserver.removeOnGlobalLayoutListener(this)
viewEffect.adjustCardSize(activity!!, binding.todayStatsCard)
}
}
override fun onCreateView(inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?): View? = DataBindingUtil
.inflate<FragmentMainMenuBinding>(inflater,
R.layout.fragment_main_menu,
container, false).run {
binding = this
lifecycleOwner = this@MainMenuFragment
navigation = activity as INavigationCallback
viewModel = activity!!.let {
ViewModelProviders
.of(it, MainViewModel.Factory(it.application))
.get(MainViewModel::class.java)
}
viewModel?.let {
user = it.activeUser
it.setUpMainMenuObservers()
}
mainMenuAppbar.addOnOffsetChangedListener(
AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOffset ->
viewEffect.onOffsetChanged(appBarLayout, verticalOffset)
})
profilePicture.setOnClickListener {
Dialogs.profilePictureDialog(activity!!, viewModel!!).show()
}
mainMenuToolbar.setUpMainMenuToolbar(navigation!!)
root.viewTreeObserver.addOnGlobalLayoutListener(globalLayoutListener)
viewEffect.startAlphaAnimation(userNameSmall, 0, View.INVISIBLE)
setHasOptionsMenu(true)
return root
}
private fun setUpBluetooth(): Boolean {
val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
activity?.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
return true
}
private fun MainViewModel.setUpMainMenuObservers(){
//this is the original call which doesn't work
activeUser.observe(activity!!, Observer {
log("Active user id = $activeUserId") //this prints correct id
if(it == null) log("USER IS NULL")
else log("USER : ${it.name}") // and this prints that user is null, so it wasn't found
tryCatch {
binding.profilePicture.setImageBitmap(getProfilePicture(it, 256))
}
})
//this was added for testing purposes. It returns a list of all users in the db.
databaseData.getAllUsers.observe(activity!!, Observer {
log("ALL USERS:")
it.forEach{user: User ->
log("NAME : ${user.name}, ID = ${user.id}") //this prints each user with the correct name and id
}
log("Active user id = $activeUserId") //this prints correct active user id
val user = it.first { id == activeUserId } // on this line app crashes, as if 1 != 1.
log("USER : ${user.name}")
tryCatch {
binding.profilePicture.setImageBitmap(getProfilePicture(user, 256))
}
})
bluetoothData.steps.observe(activity!!, Observer {
binding.stepsTodayCounter.text = it.toString()
})
bluetoothData.location.observe(activity!!, Observer {
val text = "${lastDayData.getLastDayDistanceFormatted()} Km"
binding.distanceTodayCounter.text = text
})
bluetoothData.isBluetoothConnected.observe(activity!!, Observer {
when (it) {
true -> binding.changeOnBTConnected("Connected!", R.drawable.bt_connected_icon)
false -> binding.changeOnBTConnected("Not Connected!", R.drawable.bt_disconnected_icon)
}
})
}
private fun FragmentMainMenuBinding.changeOnBTConnected(changeText: String, changeDrawable: Int){
connectionStatus.text = changeText
mainMenuToolbar.menu?.findItem(R.id.menu_bluetooth)?.icon =
activity!!.getDrawable(changeDrawable)
Toast.makeText(activity!!, "You are $changeText!", Toast.LENGTH_LONG).show()
}
private fun Toolbar.setUpMainMenuToolbar(navigation: INavigationCallback) {
inflateMenu(R.menu.main_view_menu)
menu.findItem(R.id.menu_bluetooth).setOnMenuItemClickListener {
setUpBluetooth()
}
menu.findItem(R.id.menu_settings).setOnMenuItemClickListener {
navigation.navigateTo(R.id.action_mainMenuFragment_to_settingsFragment)
true
}
}
}
Так что из комментариев вы можете понять, насколько это странно.Поэтому при тестировании запроса я получал бы отпечатки в консоли, такие как:
NAME : Slava Simonov, ID = 1
NAME : Uzi, ID = 11
Active user id = 1
Shutting down VM
FATAL EXCEPTION: main
...
Я надеюсь, что кто-нибудь сможет мне помочь, потому что у меня закончились идеи, почему это могло произойти.Это похоже на какую-то ошибку.Если вам нужны другие части моего кода, я могу прикрепить его, просто не стесняйтесь спрашивать.Спасибо всем заранее.