Refactor using ViewModel
This commit is contained in:
@@ -5,6 +5,7 @@ apply plugin: 'com.github.ben-manes.versions'
|
||||
buildscript {
|
||||
ext {
|
||||
kotlinVersion = '1.3.11'
|
||||
lifecycleVersion = '2.0.0'
|
||||
roomVersion = '2.0.0'
|
||||
}
|
||||
repositories {
|
||||
|
||||
@@ -58,11 +58,14 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycleVersion"
|
||||
kapt "androidx.room:room-compiler:$roomVersion"
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation "androidx.browser:browser:1.0.0"
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha2'
|
||||
implementation "androidx.core:core-ktx:1.0.1"
|
||||
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycleVersion"
|
||||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion"
|
||||
implementation "androidx.preference:preference:1.0.0"
|
||||
implementation "androidx.room:room-runtime:$roomVersion"
|
||||
implementation 'com.github.luongvo:BadgeView:1.1.5'
|
||||
@@ -74,6 +77,7 @@ dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
|
||||
baseImplementation 'com.android.billingclient:billing:1.2'
|
||||
baseImplementation 'com.crashlytics.sdk.android:crashlytics:2.9.7'
|
||||
testImplementation "androidx.arch.core:core-testing:$lifecycleVersion"
|
||||
testImplementation "androidx.room:room-testing:$roomVersion"
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test:runner:1.1.1'
|
||||
|
||||
@@ -82,7 +82,6 @@
|
||||
<action android:name="android.service.quicksettings.action.QS_TILE" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<service android:name=".client.ClientMonitorService"/>
|
||||
|
||||
<receiver
|
||||
android:name=".BootReceiver"
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
package be.mygod.vpnhotspot
|
||||
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import android.view.Gravity
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
@@ -14,7 +11,11 @@ import androidx.browser.customtabs.CustomTabsIntent
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.Fragment
|
||||
import be.mygod.vpnhotspot.client.ClientMonitorService
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import androidx.lifecycle.get
|
||||
import be.mygod.vpnhotspot.client.Client
|
||||
import be.mygod.vpnhotspot.client.ClientViewModel
|
||||
import be.mygod.vpnhotspot.client.ClientsFragment
|
||||
import be.mygod.vpnhotspot.databinding.ActivityMainBinding
|
||||
import be.mygod.vpnhotspot.manage.TetheringFragment
|
||||
@@ -25,10 +26,9 @@ import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import q.rorbin.badgeview.QBadgeView
|
||||
import timber.log.Timber
|
||||
|
||||
class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener, ServiceConnection {
|
||||
class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener {
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
private lateinit var badge: QBadgeView
|
||||
private var clients: ClientMonitorService.Binder? = null
|
||||
private val customTabsIntent by lazy {
|
||||
CustomTabsIntent.Builder()
|
||||
.setToolbarColor(ContextCompat.getColor(this, R.color.colorPrimary))
|
||||
@@ -56,7 +56,9 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
|
||||
badge.badgeTextColor = ContextCompat.getColor(this, R.color.primary_text_default_material_light)
|
||||
badge.badgeGravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL
|
||||
badge.setGravityOffset(16f, 0f, true)
|
||||
ServiceForegroundConnector(this, this, ClientMonitorService::class)
|
||||
val model = ViewModelProviders.of(this).get<ClientViewModel>()
|
||||
if (RepeaterService.supported) ServiceForegroundConnector(this, model, RepeaterService::class)
|
||||
model.clients.observe(this, Observer<List<Client>> { badge.badgeNumber = it.size })
|
||||
SmartSnackbar.Register(lifecycle, binding.fragmentHolder)
|
||||
}
|
||||
|
||||
@@ -85,17 +87,6 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
|
||||
else -> false
|
||||
}
|
||||
|
||||
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
||||
clients = service as ClientMonitorService.Binder
|
||||
service.clientsChanged[this] = { badge.badgeNumber = it.size }
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(name: ComponentName?) {
|
||||
val clients = clients ?: return
|
||||
this.clients = null
|
||||
clients.clientsChanged -= this
|
||||
}
|
||||
|
||||
private fun displayFragment(fragment: Fragment) =
|
||||
supportFragmentManager.beginTransaction().replace(R.id.fragmentHolder, fragment).commitAllowingStateLoss()
|
||||
|
||||
|
||||
@@ -1,24 +1,20 @@
|
||||
package be.mygod.vpnhotspot.client
|
||||
|
||||
import android.app.Service
|
||||
import android.content.*
|
||||
import android.content.ComponentName
|
||||
import android.content.IntentFilter
|
||||
import android.content.ServiceConnection
|
||||
import android.net.wifi.p2p.WifiP2pDevice
|
||||
import android.os.IBinder
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import be.mygod.vpnhotspot.App.Companion.app
|
||||
import be.mygod.vpnhotspot.RepeaterService
|
||||
import be.mygod.vpnhotspot.net.IpNeighbour
|
||||
import be.mygod.vpnhotspot.net.monitor.IpNeighbourMonitor
|
||||
import be.mygod.vpnhotspot.net.TetheringManager
|
||||
import be.mygod.vpnhotspot.util.StickyEvent1
|
||||
import be.mygod.vpnhotspot.net.monitor.IpNeighbourMonitor
|
||||
import be.mygod.vpnhotspot.util.broadcastReceiver
|
||||
import be.mygod.vpnhotspot.util.stopAndUnbind
|
||||
|
||||
class ClientMonitorService : Service(), ServiceConnection, IpNeighbourMonitor.Callback {
|
||||
inner class Binder : android.os.Binder() {
|
||||
val clientsChanged = StickyEvent1 { clients }
|
||||
}
|
||||
private val binder = Binder()
|
||||
override fun onBind(intent: Intent?) = binder
|
||||
|
||||
class ClientViewModel : ViewModel(), ServiceConnection, IpNeighbourMonitor.Callback {
|
||||
private var tetheredInterfaces = emptySet<String>()
|
||||
private val receiver = broadcastReceiver { _, intent ->
|
||||
val extras = intent.extras ?: return@broadcastReceiver
|
||||
@@ -30,11 +26,7 @@ class ClientMonitorService : Service(), ServiceConnection, IpNeighbourMonitor.Ca
|
||||
private var repeater: RepeaterService.Binder? = null
|
||||
private var p2p: Collection<WifiP2pDevice> = emptyList()
|
||||
private var neighbours = emptyList<IpNeighbour>()
|
||||
private var clients = emptyList<Client>()
|
||||
private set(value) {
|
||||
field = value
|
||||
binder.clientsChanged(value)
|
||||
}
|
||||
val clients = MutableLiveData<List<Client>>()
|
||||
|
||||
private fun populateClients() {
|
||||
val clients = HashMap<Pair<String, String>, Client>()
|
||||
@@ -53,7 +45,7 @@ class ClientMonitorService : Service(), ServiceConnection, IpNeighbourMonitor.Ca
|
||||
}
|
||||
client.ip += Pair(neighbour.ip, neighbour.state)
|
||||
}
|
||||
this.clients = clients.values.sortedWith(compareBy<Client> { it.iface }.thenBy { it.mac })
|
||||
this.clients.postValue(clients.values.sortedWith(compareBy<Client> { it.iface }.thenBy { it.mac }))
|
||||
}
|
||||
|
||||
private fun refreshP2p() {
|
||||
@@ -62,20 +54,14 @@ class ClientMonitorService : Service(), ServiceConnection, IpNeighbourMonitor.Ca
|
||||
populateClients()
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
if (RepeaterService.supported) {
|
||||
bindService(Intent(this, RepeaterService::class.java), this, Context.BIND_AUTO_CREATE)
|
||||
}
|
||||
init {
|
||||
app.registerReceiver(receiver, IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED))
|
||||
IpNeighbourMonitor.registerCallback(this)
|
||||
registerReceiver(receiver, IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED))
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
unregisterReceiver(receiver)
|
||||
override fun onCleared() {
|
||||
IpNeighbourMonitor.unregisterCallback(this)
|
||||
if (RepeaterService.supported) stopAndUnbind(this)
|
||||
super.onDestroy()
|
||||
app.unregisterReceiver(receiver)
|
||||
}
|
||||
|
||||
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
||||
@@ -1,10 +1,7 @@
|
||||
package be.mygod.vpnhotspot.client
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.DialogInterface
|
||||
import android.content.ServiceConnection
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import android.text.format.DateUtils
|
||||
import android.text.format.Formatter
|
||||
import android.util.LongSparseArray
|
||||
@@ -19,6 +16,9 @@ import androidx.core.os.bundleOf
|
||||
import androidx.databinding.BaseObservable
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import androidx.lifecycle.get
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
@@ -31,13 +31,12 @@ import be.mygod.vpnhotspot.databinding.ListitemClientBinding
|
||||
import be.mygod.vpnhotspot.net.monitor.IpNeighbourMonitor
|
||||
import be.mygod.vpnhotspot.net.monitor.TrafficRecorder
|
||||
import be.mygod.vpnhotspot.room.*
|
||||
import be.mygod.vpnhotspot.util.ServiceForegroundConnector
|
||||
import be.mygod.vpnhotspot.util.computeIfAbsentCompat
|
||||
import be.mygod.vpnhotspot.util.toPluralInt
|
||||
import be.mygod.vpnhotspot.widget.SmartSnackbar
|
||||
import java.text.NumberFormat
|
||||
|
||||
class ClientsFragment : Fragment(), ServiceConnection {
|
||||
class ClientsFragment : Fragment() {
|
||||
class NicknameDialogFragment : AlertDialogFragment() {
|
||||
companion object {
|
||||
const val KEY_MAC = "mac"
|
||||
@@ -198,7 +197,6 @@ class ClientsFragment : Fragment(), ServiceConnection {
|
||||
|
||||
private lateinit var binding: FragmentClientsBinding
|
||||
private val adapter = ClientAdapter()
|
||||
private var clients: ClientMonitorService.Binder? = null
|
||||
private var rates = HashMap<Pair<String, Long>, TrafficRate>()
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
@@ -210,21 +208,11 @@ class ClientsFragment : Fragment(), ServiceConnection {
|
||||
binding.swipeRefresher.setOnRefreshListener {
|
||||
IpNeighbourMonitor.instance?.flush()
|
||||
}
|
||||
ServiceForegroundConnector(this, this, ClientMonitorService::class)
|
||||
ViewModelProviders.of(requireActivity()).get<ClientViewModel>().clients.observe(this,
|
||||
Observer<List<Client>> { adapter.submitList(it.toMutableList()) })
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
||||
clients = service as ClientMonitorService.Binder
|
||||
service.clientsChanged[this] = { adapter.submitList(it.toMutableList()) }
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(name: ComponentName?) {
|
||||
val clients = clients ?: return
|
||||
clients.clientsChanged -= this
|
||||
this.clients = null
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
// we just put these two thing together as this is the only place we need to use this event for now
|
||||
|
||||
Reference in New Issue
Block a user