mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
Introduce Hilt dependency injection
Uses Hilt to get the database initialization off of the main thread. The initial introduction always has a disproportionate fan-out of boilerplate. In this case, all entry points which were using UIViewModel needed to be annotated in order to let the code gen know that they needed to support it. The PacketRepository is injected into things via the main thread (e.g., the MeshService) but due to the lazy declaration, the database isn't hydrated until the DAO is access while on an IO thread.
This commit is contained in:
parent
1f177dc63e
commit
654a32c01c
18 changed files with 131 additions and 66 deletions
|
|
@ -7,18 +7,20 @@ import android.net.Uri
|
|||
import android.os.RemoteException
|
||||
import android.view.Menu
|
||||
import androidx.core.content.edit
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.geeksville.android.Logging
|
||||
import com.geeksville.mesh.*
|
||||
import com.geeksville.mesh.database.MeshtasticDatabase
|
||||
import com.geeksville.mesh.database.PacketRepository
|
||||
import com.geeksville.mesh.database.entity.Packet
|
||||
import com.geeksville.mesh.service.MeshService
|
||||
import com.geeksville.mesh.ui.positionToMeter
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
|
@ -26,6 +28,7 @@ import java.io.BufferedWriter
|
|||
import java.io.FileWriter
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/// Given a human name, strip out the first letter of the first three words and return that as the initials for
|
||||
|
|
@ -51,20 +54,25 @@ fun getInitials(nameIn: String): String {
|
|||
return initials.take(nchars)
|
||||
}
|
||||
|
||||
class UIViewModel(private val app: Application) : AndroidViewModel(app), Logging {
|
||||
@HiltViewModel
|
||||
class UIViewModel @Inject constructor(
|
||||
private val app: Application,
|
||||
private val repository: PacketRepository,
|
||||
private val preferences: SharedPreferences
|
||||
) : ViewModel(), Logging {
|
||||
|
||||
private val repository: PacketRepository
|
||||
|
||||
val allPackets: LiveData<List<Packet>>
|
||||
private val _allPacketState = MutableStateFlow<List<Packet>>(emptyList())
|
||||
val allPackets: StateFlow<List<Packet>> = _allPacketState
|
||||
|
||||
init {
|
||||
val packetsDao = MeshtasticDatabase.getDatabase(app).packetDao()
|
||||
repository = PacketRepository(packetsDao)
|
||||
allPackets = repository.allPackets
|
||||
viewModelScope.launch {
|
||||
repository.getAllPackets().collect { packets ->
|
||||
_allPacketState.value = packets
|
||||
}
|
||||
}
|
||||
debug("ViewModel created")
|
||||
}
|
||||
|
||||
|
||||
fun insertPacket(packet: Packet) = viewModelScope.launch(Dispatchers.IO) {
|
||||
repository.insert(packet)
|
||||
}
|
||||
|
|
@ -78,8 +86,6 @@ class UIViewModel(private val app: Application) : AndroidViewModel(app), Logging
|
|||
context.getSharedPreferences("ui-prefs", Context.MODE_PRIVATE)
|
||||
}
|
||||
|
||||
private val context: Context get() = app.applicationContext
|
||||
|
||||
var actionBarMenu: Menu? = null
|
||||
|
||||
var meshService: IMeshService? = null
|
||||
|
|
@ -208,7 +214,7 @@ class UIViewModel(private val app: Application) : AndroidViewModel(app), Logging
|
|||
channels.value =
|
||||
c // Must be done after calling the service, so we will will properly throw if the service failed (and therefore not cache invalid new settings)
|
||||
|
||||
getPreferences(context).edit(commit = true) {
|
||||
preferences.edit(commit = true) {
|
||||
this.putString("channel-url", c.getChannelUrl().toString())
|
||||
}
|
||||
}
|
||||
|
|
@ -226,11 +232,11 @@ class UIViewModel(private val app: Application) : AndroidViewModel(app), Logging
|
|||
val bluetoothEnabled = object : MutableLiveData<Boolean>(false) {
|
||||
}
|
||||
|
||||
val provideLocation = object : MutableLiveData<Boolean>(getPreferences(context).getBoolean(MyPreferences.provideLocationKey, false)) {
|
||||
val provideLocation = object : MutableLiveData<Boolean>(preferences.getBoolean(MyPreferences.provideLocationKey, false)) {
|
||||
override fun setValue(value: Boolean) {
|
||||
super.setValue(value)
|
||||
|
||||
getPreferences(context).edit(commit = true) {
|
||||
preferences.edit(commit = true) {
|
||||
this.putBoolean(MyPreferences.provideLocationKey, value)
|
||||
}
|
||||
}
|
||||
|
|
@ -246,7 +252,7 @@ class UIViewModel(private val app: Application) : AndroidViewModel(app), Logging
|
|||
ownerName.value = s
|
||||
|
||||
// note: we allow an empty userstring to be written to prefs
|
||||
getPreferences(context).edit(commit = true) {
|
||||
preferences.edit(commit = true) {
|
||||
putString("owner", s)
|
||||
}
|
||||
}
|
||||
|
|
@ -286,7 +292,7 @@ class UIViewModel(private val app: Application) : AndroidViewModel(app), Logging
|
|||
// our device in localNodePosition.
|
||||
var localNodePosition: MeshProtos.Position? = null
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd,HH:mm:ss", Locale.getDefault())
|
||||
repository.allPacketsInReceiveOrder.first().forEach { packet ->
|
||||
repository.getAllPacketsInReceiveOrder().first().forEach { packet ->
|
||||
packet.proto?.let { proto ->
|
||||
packet.position?.let { position ->
|
||||
if (proto.from == myNodeNum) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue