- Move the method to updateBalances from the MainActivity to the ConnectedActivity, so that it can be always trying to update the Balances even if we are not in the MainActivity and also to be able to update the Balances right after we notice there are new transactions for the current BitShares account.

- Move the TransfersLoader from MainActivity for the same reason than the updateBalances method described above and fix it so that it no longer needs the activity Lifecycle.
This commit is contained in:
Severiano Jaramillo 2018-12-08 22:55:28 -06:00
parent 0f96c48135
commit 50a266ffb4
3 changed files with 68 additions and 95 deletions

View file

@ -13,13 +13,17 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import cy.agorise.bitsybitshareswallet.database.entities.Balance
import cy.agorise.bitsybitshareswallet.processors.TransfersLoader
import cy.agorise.bitsybitshareswallet.repositories.BalanceRepository
import cy.agorise.bitsybitshareswallet.utils.Constants
import cy.agorise.bitsybitshareswallet.viewmodels.UserAccountViewModel
import cy.agorise.graphenej.AssetAmount
import cy.agorise.graphenej.UserAccount
import cy.agorise.graphenej.api.ConnectionStatusUpdate
import cy.agorise.graphenej.api.android.NetworkService
import cy.agorise.graphenej.api.android.RxBus
import cy.agorise.graphenej.api.calls.GetAccountBalances
import cy.agorise.graphenej.api.calls.GetAccounts
import cy.agorise.graphenej.api.calls.GetFullAccounts
import cy.agorise.graphenej.models.AccountProperties
@ -37,6 +41,8 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
private lateinit var mUserAccountViewModel: UserAccountViewModel
private var mBalanceRepository: BalanceRepository? = null
/* Current user account */
protected var mCurrentAccount: UserAccount? = null
@ -65,6 +71,20 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
if (userId != "")
mCurrentAccount = UserAccount(userId)
mBalanceRepository = BalanceRepository(this)
// Configure UserAccountViewModel to show the current account
mUserAccountViewModel = ViewModelProviders.of(this).get(UserAccountViewModel::class.java)
mUserAccountViewModel.getMissingUserAccountIds().observe(this, Observer<List<String>>{ userAccountIds ->
if (userAccountIds.isNotEmpty()) {
for (userAccountId in userAccountIds)
missingUserAccounts.add(UserAccount(userAccountId))
mHandler.postDelayed(mRequestMissingUserAccountsTask, Constants.NETWORK_SERVICE_RETRY_PERIOD)
}
})
mDisposable = RxBus.getBusInstance()
.asFlowable()
.observeOn(AndroidSchedulers.mainThread())
@ -79,6 +99,8 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
handleAccountDetails((message.result as List<*>)[0] as FullAccountDetails)
} else if ((message.result as List<*>)[0] is AccountProperties) {
handleAccountProperties(message.result as List<AccountProperties>)
} else if((message.result as List<*>)[0] is AssetAmount) {
handleBalanceUpdate(message.result as List<AssetAmount>)
}
}
} else {
@ -92,26 +114,10 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
}
} else if (message is ConnectionStatusUpdate) {
handleConnectionStatusUpdate(message)
if (message.updateCode == ConnectionStatusUpdate.DISCONNECTED) {
// recurrentAccountUpdateId = -1
// accountOpRequestId = -1
}
}
}
// Configure UserAccountViewModel to show the current account
mUserAccountViewModel = ViewModelProviders.of(this).get(UserAccountViewModel::class.java)
mUserAccountViewModel.getMissingUserAccountIds().observe(this, Observer<List<String>>{ userAccountIds ->
if (userAccountIds.isNotEmpty()) {
for (userAccountId in userAccountIds)
missingUserAccounts.add(UserAccount(userAccountId))
mHandler.postDelayed(mRequestMissingUserAccountsTask, Constants.NETWORK_SERVICE_RETRY_PERIOD)
}
})
}
/**
* Method called whenever a response to the 'get_full_accounts' API call has been detected.
* @param accountDetails De-serialized account details object
@ -125,13 +131,16 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
"\nAsk the NetworkService to remove the node from the list and connect to another one.")
mNetworkService!!.removeCurrentNodeAndReconnect()
} else if (storedOpCount == -1L) {
// Initial case
// Initial case when the app starts
storedOpCount = latestOpCount
PreferenceManager.getDefaultSharedPreferences(this)
.edit().putLong(Constants.KEY_ACCOUNT_OPERATION_COUNT, latestOpCount).apply()
TransfersLoader(this)
updateBalances()
} else if (latestOpCount > storedOpCount) {
storedOpCount = latestOpCount
TransfersLoader(this, lifecycle)
TransfersLoader(this)
updateBalances()
}
}
@ -152,6 +161,31 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
missingUserAccounts.clear()
}
private fun handleBalanceUpdate(assetAmountList: List<AssetAmount>) {
Log.d(TAG, "handleBalanceUpdate")
val now = System.currentTimeMillis() / 1000
val balances = ArrayList<Balance>()
for (assetAmount in assetAmountList) {
val balance = Balance(
assetAmount.asset.objectId,
assetAmount.amount.toLong(),
now
)
balances.add(balance)
}
mBalanceRepository!!.insertAll(balances)
}
private fun updateBalances() {
if (mNetworkService!!.isConnected) {
mNetworkService!!.sendMessage(
GetAccountBalances(mCurrentAccount, ArrayList()),
GetAccountBalances.REQUIRED_API
)
}
}
/**
* Task used to obtain the missing UserAccounts.
*/
@ -171,13 +205,14 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
private val mCheckMissingPaymentsTask = object : Runnable {
override fun run() {
if (mNetworkService != null && mNetworkService!!.isConnected) {
// Checking that we actually have a user id registered in the shared preferences
if (mCurrentAccount != null) {
val userAccounts = ArrayList<String>()
userAccounts.add(mCurrentAccount!!.objectId)
mNetworkService!!.sendMessage(
GetFullAccounts(userAccounts, false),
GetFullAccounts.REQUIRED_API
)
}
} else {
Log.w(TAG, "NetworkService is null or is not connected. mNetworkService: $mNetworkService")
}
@ -214,9 +249,6 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
Log.e(TAG, "Binding to the network service failed.")
}
mHandler.postDelayed(mCheckMissingPaymentsTask, Constants.MISSING_PAYMENT_CHECK_PERIOD)
storedOpCount = PreferenceManager.getDefaultSharedPreferences(this)
.getLong(Constants.KEY_ACCOUNT_OPERATION_COUNT, -1)
}
override fun onDestroy() {

View file

@ -2,36 +2,22 @@ package cy.agorise.bitsybitshareswallet.activities
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import androidx.collection.LongSparseArray
import androidx.fragment.app.Fragment
import com.google.android.material.bottomnavigation.BottomNavigationView
import cy.agorise.bitsybitshareswallet.R
import cy.agorise.bitsybitshareswallet.database.entities.Balance
import cy.agorise.bitsybitshareswallet.fragments.BalancesFragment
import cy.agorise.bitsybitshareswallet.fragments.MerchantsFragment
import cy.agorise.bitsybitshareswallet.fragments.ReceiveTransactionFragment
import cy.agorise.bitsybitshareswallet.fragments.SendTransactionFragment
import cy.agorise.bitsybitshareswallet.processors.TransfersLoader
import cy.agorise.bitsybitshareswallet.repositories.BalanceRepository
import cy.agorise.graphenej.AssetAmount
import cy.agorise.graphenej.RPC
import cy.agorise.graphenej.api.ApiAccess
import cy.agorise.graphenej.api.ConnectionStatusUpdate
import cy.agorise.graphenej.api.calls.GetAccountBalances
import cy.agorise.graphenej.models.JsonRpcResponse
import kotlinx.android.synthetic.main.activity_main.*
import java.util.ArrayList
class MainActivity : ConnectedActivity() {
private val TAG = this.javaClass.simpleName
private val requestMap = LongSparseArray<String>()
private var mBalanceRepository: BalanceRepository? = null
private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_receive -> {
@ -60,8 +46,6 @@ class MainActivity : ConnectedActivity() {
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
navigation.selectedItemId = R.id.navigation_balances
mBalanceRepository = BalanceRepository(this)
}
private fun loadFragment(fragment: Fragment) {
@ -88,9 +72,7 @@ class MainActivity : ConnectedActivity() {
}
override fun handleJsonRpcResponse(response: JsonRpcResponse<*>) {
if (requestMap.get(response.id) == RPC.CALL_GET_ACCOUNT_BALANCES) {
handleBalanceUpdate(response as JsonRpcResponse<List<AssetAmount>>)
}
}
/**
@ -102,46 +84,7 @@ class MainActivity : ConnectedActivity() {
ConnectionStatusUpdate.CONNECTED -> { /* Do nothing for now */ }
ConnectionStatusUpdate.DISCONNECTED -> { /* Do nothing for now */ }
ConnectionStatusUpdate.AUTHENTICATED -> {}//updateBalances() }
ConnectionStatusUpdate.API_UPDATE -> {
// In certain cases the information about the accounts is not complete, this may not be the best
// solution but at least it works. Feel free to improve it or move it to a better place
//MissingAccountsLoader(this, lifecycle)
if (connectionStatusUpdate.api == ApiAccess.API_NETWORK_BROADCAST) {
Log.d(TAG, "ConnectionStatusUpdate: API_NETWORK_BROADCAST")
// Instantiating this loader is enough to kick-start the transfers loading procedure
TransfersLoader(this, lifecycle)
updateBalances()
ConnectionStatusUpdate.API_UPDATE -> { }
}
}
}
}
private fun updateBalances() {
if (mNetworkService!!.isConnected) {
val id = mNetworkService!!.sendMessage(
GetAccountBalances(mCurrentAccount, ArrayList()),
GetAccountBalances.REQUIRED_API
)
requestMap.put(id, RPC.CALL_GET_ACCOUNT_BALANCES)
}
}
private fun handleBalanceUpdate(response: JsonRpcResponse<List<AssetAmount>>) {
Log.d(TAG, "handleBalanceUpdate")
val now = System.currentTimeMillis() / 1000
val assetBalances = response.result
val balances = ArrayList<Balance>()
for (assetBalance in assetBalances) {
val balance = Balance(
assetBalance.asset.objectId,
assetBalance.amount.toLong(),
now
)
balances.add(balance)
}
mBalanceRepository!!.insertAll(balances)
}
}

View file

@ -48,8 +48,7 @@ import javax.crypto.AEADBadTagException
* for every transfer, we must first load all historical transfer operations, and then proceed to
* handle those missing columns.
*/
class TransfersLoader(private var mContext: Context?, private val mLifeCycle: Lifecycle) : LifecycleObserver,
ServiceConnection {
class TransfersLoader(private var mContext: Context?): ServiceConnection {
private val TAG = this.javaClass.simpleName
@ -106,7 +105,6 @@ class TransfersLoader(private var mContext: Context?, private val mLifeCycle: Li
}
init {
this.mLifeCycle.addObserver(this)
transferRepository = TransferRepository(mContext!!)
authorityRepository = AuthorityRepository(mContext!!)
@ -152,6 +150,8 @@ class TransfersLoader(private var mContext: Context?, private val mLifeCycle: Li
// If there is no current user, we should not do anything
mState = State.CANCELLED
}
onStart()
}
override fun onServiceDisconnected(name: ComponentName?) {
@ -167,8 +167,7 @@ class TransfersLoader(private var mContext: Context?, private val mLifeCycle: Li
startTransfersUpdateProcedure()
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
internal fun onStart() {
private fun onStart() {
if (mState != State.CANCELLED) {
val intent = Intent(mContext, NetworkService::class.java)
if (mContext!!.bindService(intent, this, Context.BIND_AUTO_CREATE)) {
@ -219,7 +218,7 @@ class TransfersLoader(private var mContext: Context?, private val mLifeCycle: Li
// TODO return number of inserted rows
// Log.d(TAG, String.format("Inserted count: %d, list size: %d", insertedCount, operationHistoryList.size))
if (/* insertedCount == 0 && */ operationHistoryList.isEmpty()) {
// TODO Terminate process and obtain MissingTimes and MissingEquivalentValues
onDestroy()
} else {
// If we inserted more than one operation, we cannot yet be sure we've reached the
@ -320,8 +319,7 @@ class TransfersLoader(private var mContext: Context?, private val mLifeCycle: Li
return transfers
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
internal fun onDestroy() {
private fun onDestroy() {
Log.d(TAG, "Destroying TransfersLoader")
if (!mDisposables.isDisposed) mDisposables.dispose()
if (mShouldUnbindNetwork) {