Move more database queries away from the main thread

This commit is contained in:
Stefan Niedermann 2020-12-31 16:16:17 +01:00
parent 82b2719a77
commit 69d383f9f8
6 changed files with 69 additions and 37 deletions

View file

@ -146,19 +146,25 @@ public class NotesDaoTest {
}
@Test
public void getFavoritesCount() throws NextcloudHttpRequestFailedException {
public void getFavoritesCount() throws NextcloudHttpRequestFailedException, InterruptedException {
final Account secondAccount = setupSecondAccountAndTestNotes();
assertEquals(Integer.valueOf(1), db.getNoteDao().getFavoritesCount(account.getId()));
assertEquals(Integer.valueOf(1), db.getNoteDao().getFavoritesCount(secondAccount.getId()));
assertEquals(Integer.valueOf(1), getOrAwaitValue(db.getNoteDao().getFavoritesCountLiveData(account.getId())));
assertEquals(Integer.valueOf(1), getOrAwaitValue(db.getNoteDao().getFavoritesCountLiveData(secondAccount.getId())));
}
@Test
public void count() throws NextcloudHttpRequestFailedException {
public void count() throws NextcloudHttpRequestFailedException, InterruptedException {
final Account secondAccount = setupSecondAccountAndTestNotes();
assertEquals(Integer.valueOf(7), db.getNoteDao().count(account.getId()));
assertEquals(Integer.valueOf(5), db.getNoteDao().count(secondAccount.getId()));
assertEquals(Integer.valueOf(7), getOrAwaitValue(db.getNoteDao().countLiveData(account.getId())));
assertEquals(Integer.valueOf(5), getOrAwaitValue(db.getNoteDao().countLiveData(secondAccount.getId())));
}
@Test

View file

@ -10,6 +10,7 @@ import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.LiveData;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
@ -62,29 +63,36 @@ public class AccountSwitcherDialog extends BrandedDialogFragment {
public Dialog onCreateDialog(Bundle savedInstanceState) {
binding = DialogAccountSwitcherBinding.inflate(requireActivity().getLayoutInflater());
Account currentLocalAccount = db.getAccountDao().getAccount(currentAccountId);
binding.accountName.setText(currentLocalAccount.getUserName());
binding.accountHost.setText(Uri.parse(currentLocalAccount.getUrl()).getHost());
Glide.with(requireContext())
.load(currentLocalAccount.getUrl() + "/index.php/avatar/" + Uri.encode(currentLocalAccount.getUserName()) + "/64")
.error(R.drawable.ic_account_circle_grey_24dp)
.apply(RequestOptions.circleCropTransform())
.into(binding.currentAccountItemAvatar);
binding.accountLayout.setOnClickListener((v) -> dismiss());
LiveData<Account> account$ = db.getAccountDao().getAccountLiveData(currentAccountId);
account$.observe(requireActivity(), (currentLocalAccount) -> {
account$.removeObservers(requireActivity());
AccountSwitcherAdapter adapter = new AccountSwitcherAdapter((localAccount -> {
accountSwitcherListener.onAccountChosen(localAccount);
dismiss();
}));
binding.accountsList.setAdapter(adapter);
List<Account> localAccounts = db.getAccountDao().getAccounts();
for (Account localAccount : localAccounts) {
if (localAccount.getId() == currentLocalAccount.getId()) {
localAccounts.remove(localAccount);
break;
}
}
adapter.setLocalAccounts(localAccounts);
binding.accountName.setText(currentLocalAccount.getUserName());
binding.accountHost.setText(Uri.parse(currentLocalAccount.getUrl()).getHost());
Glide.with(requireContext())
.load(currentLocalAccount.getUrl() + "/index.php/avatar/" + Uri.encode(currentLocalAccount.getUserName()) + "/64")
.error(R.drawable.ic_account_circle_grey_24dp)
.apply(RequestOptions.circleCropTransform())
.into(binding.currentAccountItemAvatar);
binding.accountLayout.setOnClickListener((v) -> dismiss());
AccountSwitcherAdapter adapter = new AccountSwitcherAdapter((localAccount -> {
accountSwitcherListener.onAccountChosen(localAccount);
dismiss();
}));
binding.accountsList.setAdapter(adapter);
LiveData<List<Account>> localAccounts$ = db.getAccountDao().getAccountsLiveData();
localAccounts$.observe(requireActivity(), (localAccounts) -> {
localAccounts$.removeObservers(requireActivity());
for (Account localAccount : localAccounts) {
if (localAccount.getId() == currentLocalAccount.getId()) {
localAccounts.remove(localAccount);
break;
}
}
adapter.setLocalAccounts(localAccounts);
});
});
binding.addAccount.setOnClickListener((v) -> {
accountSwitcherListener.addAccount();

View file

@ -160,11 +160,14 @@ public class MainActivity extends LockedActivity implements NoteClickListener, A
if (count == 0) {
startActivityForResult(new Intent(this, ImportAccountActivity.class), ImportAccountActivity.REQUEST_CODE_IMPORT_ACCOUNT);
} else {
try {
mainViewModel.postCurrentAccount(mainViewModel.getLocalAccountByAccountName(SingleAccountHelper.getCurrentSingleSignOnAccount(getApplicationContext()).name));
} catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
ExceptionDialogFragment.newInstance(e).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName());
}
new Thread(() -> {
try {
final Account account = mainViewModel.getLocalAccountByAccountName(SingleAccountHelper.getCurrentSingleSignOnAccount(getApplicationContext()).name);
runOnUiThread(() -> mainViewModel.postCurrentAccount(account));
} catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
runOnUiThread(() -> ExceptionDialogFragment.newInstance(e).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()));
}
}).start();
}
});
@ -599,8 +602,11 @@ public class MainActivity extends LockedActivity implements NoteClickListener, A
final Capabilities capabilities = CapabilitiesClient.getCapabilities(getApplicationContext(), ssoAccount, null);
LiveData<Account> createLiveData = mainViewModel.addAccount(ssoAccount.url, ssoAccount.userId, ssoAccount.name, capabilities);
runOnUiThread(() -> createLiveData.observe(this, (account) -> {
Log.i(TAG, capabilities.toString());
runOnUiThread(() -> mainViewModel.postCurrentAccount(mainViewModel.getLocalAccountByAccountName(ssoAccount.name)));
new Thread(() -> {
Log.i(TAG, capabilities.toString());
final Account a = mainViewModel.getLocalAccountByAccountName(ssoAccount.name);
runOnUiThread(() -> mainViewModel.postCurrentAccount(a));
}).start();
}));
} catch (Exception e) {
// Happens when importing an already existing account the second time

View file

@ -10,12 +10,9 @@ import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import androidx.arch.core.util.Function;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MediatorLiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.SavedStateHandle;
import com.nextcloud.android.sso.AccountImporter;
@ -294,9 +291,15 @@ public class MainViewModel extends AndroidViewModel {
Log.v(TAG, "[getNavigationCategories] - currentAccount: " + currentAccount.getAccountName());
return switchMap(getExpandedCategory(), expandedCategory -> {
Log.v(TAG, "[getNavigationCategories] - expandedCategory: " + expandedCategory);
return distinctUntilChanged(map(db.getNoteDao().getCategoriesLiveData(currentAccount.getId()), fromDatabase ->
fromCategoriesWithNotesCount(getApplication(), expandedCategory, fromDatabase, db.getNoteDao().count(currentAccount.getId()), db.getNoteDao().getFavoritesCount(currentAccount.getId()))
));
return switchMap(db.getNoteDao().countLiveData(currentAccount.getId()), (count) -> {
Log.v(TAG, "[getNavigationCategories] - count: " + count);
return switchMap(db.getNoteDao().getFavoritesCountLiveData(currentAccount.getId()), (favoritesCount) -> {
Log.v(TAG, "[getNavigationCategories] - favoritesCount: " + favoritesCount);
return distinctUntilChanged(map(db.getNoteDao().getCategoriesLiveData(currentAccount.getId()), fromDatabase ->
fromCategoriesWithNotesCount(getApplication(), expandedCategory, fromDatabase, count, favoritesCount)
));
});
});
});
}
});

View file

@ -32,6 +32,9 @@ public interface AccountDao {
@Query("SELECT * FROM Account")
List<Account> getAccounts();
@Query("SELECT * FROM Account")
LiveData<List<Account>> getAccountsLiveData();
@Query("SELECT COUNT(*) FROM Account")
Integer getAccountsCount();

View file

@ -93,9 +93,15 @@ public interface NoteDao {
@Query("SELECT COUNT(*) FROM NOTE WHERE status != 'LOCAL_DELETED' AND accountId = :accountId AND favorite = 1")
Integer getFavoritesCount(long accountId);
@Query("SELECT COUNT(*) FROM NOTE WHERE status != 'LOCAL_DELETED' AND accountId = :accountId AND favorite = 1")
LiveData<Integer> getFavoritesCountLiveData(long accountId);
@Query("SELECT COUNT(*) FROM NOTE WHERE status != 'LOCAL_DELETED' AND accountId = :accountId")
Integer count(long accountId);
@Query("SELECT COUNT(*) FROM NOTE WHERE status != 'LOCAL_DELETED' AND accountId = :accountId")
LiveData<Integer> countLiveData(long accountId);
/**
* Returns a list of all {@link Note}s in the Database which were modified locally
*