Refactor using ViewModel

This commit is contained in:
Mygod
2018-12-21 14:53:12 +08:00
parent e9421fd24f
commit f1db0f2c8f
6 changed files with 34 additions and 65 deletions

View File

@@ -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 {

View File

@@ -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'

View File

@@ -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"

View File

@@ -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()

View File

@@ -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?) {

View File

@@ -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