Refactor connection initialization

Until now, connection was started at the very end of onCreate(). As a
result components like Dispatcher could not rely on VncViewModel's
profile during their initialization. Now initialization happen at
the beginning.

It also comes with a tiny bit of performance improvement.
Receiver thread can now start the connection early, while main thread
is still creating the UI.
This commit is contained in:
Gaurav Ujjwal 2022-07-31 22:33:29 +05:30
parent a28149eb99
commit ee8ae23d5f
3 changed files with 30 additions and 31 deletions

View file

@ -9,7 +9,6 @@
package com.gaurav.avnc.ui.vnc
import android.content.Context
import android.content.Intent
import android.view.inputmethod.InputMethodManager
import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.Espresso.onIdle
@ -36,8 +35,7 @@ class VncActivityTest {
testServer.start()
val profile = ServerProfile(host = testServer.host, port = testServer.port)
val intent = Intent(targetContext, VncActivity::class.java)
.putExtra("com.gaurav.avnc.server_profile", profile)
val intent = createVncIntent(targetContext, profile)
ActivityScenario.launch<VncActivity>(intent).use {
onView(withId(R.id.frame_view)).checkWillBeDisplayed() // Wait for connection

View file

@ -41,10 +41,14 @@ import java.lang.ref.WeakReference
private const val PROFILE_KEY = "com.gaurav.avnc.server_profile"
fun createVncIntent(context: Context, profile: ServerProfile): Intent {
return Intent(context, VncActivity::class.java).apply {
putExtra(PROFILE_KEY, profile)
}
}
fun startVncActivity(source: Activity, profile: ServerProfile) {
val intent = Intent(source, VncActivity::class.java)
intent.putExtra(PROFILE_KEY, profile)
source.startActivity(intent)
source.startActivity(createVncIntent(source, profile))
}
fun startVncActivity(source: Activity, uri: VncUri) {
@ -59,7 +63,7 @@ fun startVncActivity(source: Activity, uri: VncUri) {
*/
class VncActivity : AppCompatActivity() {
private val profile by lazy { loadProfile() }
private lateinit var profile: ServerProfile
val viewModel by viewModels<VncViewModel>()
lateinit var binding: ActivityVncBinding
private val dispatcher by lazy { Dispatcher(this) }
@ -69,27 +73,29 @@ class VncActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
profile = loadProfile()
viewModel.initConnection(profile)
//Main UI
binding = DataBindingUtil.setContentView(this, R.layout.activity_vnc)
binding.viewModel = viewModel
binding.lifecycleOwner = this
binding.frameView.initialize(this)
viewModel.frameViewRef = WeakReference(binding.frameView)
setupLayout()
binding.frameView.initialize(this)
binding.retryConnectionBtn.setOnClickListener { retryConnection() }
//Drawers
setupDrawerLayout()
//Buttons
binding.keyboardBtn.setOnClickListener { showKeyboard(); closeDrawers() }
binding.zoomResetBtn.setOnClickListener { viewModel.resetZoom(); closeDrawers() }
binding.virtualKeysBtn.setOnClickListener { virtualKeys.show(); closeDrawers() }
binding.retryConnectionBtn.setOnClickListener { retryConnection() }
//ViewModel setup
viewModel.frameViewRef = WeakReference(binding.frameView)
//Observers
viewModel.credentialRequest.observe(this) { showCredentialDialog() }
viewModel.sshHostKeyVerifyRequest.observe(this) { showHostKeyDialog() }
viewModel.state.observe(this) { onClientStateChanged(it) }
viewModel.initConnection(profile) //Should be called after observers has been setup
}
override fun onResume() {
@ -116,14 +122,11 @@ class VncActivity : AppCompatActivity() {
private fun loadProfile(): ServerProfile {
val profile = intent.getParcelableExtra<ServerProfile>(PROFILE_KEY)
if (profile != null) {
// Make a copy to avoid modifying intent's instance,
// because we may need the original if we have to retry connection.
return profile.copy()
}
check(profile != null) { "ServerProfile is missing from VncActivity Intent" }
Log.e(javaClass.simpleName, "No connection information was passed through Intent.")
return ServerProfile()
// Make a copy to avoid modifying intent's instance,
// because we may need the original if we have to retry connection.
return profile.copy()
}
private fun retryConnection() {

View file

@ -92,7 +92,7 @@ class VncViewModel(app: Application) : BaseViewModel(app), VncClient.Observer {
/**
* [ServerProfile] used for current connection.
*/
var profile = ServerProfile()
var profile = ServerProfile(); private set
/**
* We have two places for connection state (both are synced):
@ -167,16 +167,14 @@ class VncViewModel(app: Application) : BaseViewModel(app), VncClient.Observer {
/**
* Initialize VNC connection using given profile.
* [initConnection] can be called multiple times due to activity restarts.
* It may be called multiple times due to activity restarts.
*/
fun initConnection(profile: ServerProfile) {
if (state.value != State.Created)
return
this.profile = profile
state.value = State.Connecting
launchConnection()
if (state.value == State.Created) {
state.value = State.Connecting
this.profile = profile
launchConnection()
}
}
private fun launchConnection() {