package net.ktnx.mobileledger.async;
import android.annotation.SuppressLint;
-import android.os.AsyncTask;
import android.os.OperationCanceledException;
import androidx.annotation.NonNull;
import net.ktnx.mobileledger.model.LedgerAccount;
import net.ktnx.mobileledger.model.LedgerTransaction;
import net.ktnx.mobileledger.model.LedgerTransactionAccount;
-import net.ktnx.mobileledger.ui.MainModel;
import net.ktnx.mobileledger.utils.Logger;
import net.ktnx.mobileledger.utils.NetworkUtil;
import java.util.regex.Pattern;
-public class RetrieveTransactionsTask extends
- AsyncTask<Void, RetrieveTransactionsTask.Progress, RetrieveTransactionsTask.Result> {
+public class RetrieveTransactionsTask extends Thread {
private static final int MATCHING_TRANSACTIONS_LIMIT = 150;
private static final Pattern reComment = Pattern.compile("^\\s*;");
private static final Pattern reTransactionStart = Pattern.compile(
Pattern.compile("/register\\?q=inacct%3A([a-zA-Z0-9%]+)\"");
private final Pattern reAccountValue = Pattern.compile(
"<span class=\"[^\"]*\\bamount\\b[^\"]*\">\\s*([-+]?[\\d.,]+)(?:\\s+(\\S+))?</span>");
- private final MainModel mainModel;
private final Profile profile;
private int expectedPostingsCount = -1;
- public RetrieveTransactionsTask(@NonNull MainModel mainModel, @NonNull Profile profile) {
- this.mainModel = mainModel;
+ public RetrieveTransactionsTask(@NonNull Profile profile) {
this.profile = profile;
}
private static void L(String msg) {
return null;
}
}
- @Override
- protected void onProgressUpdate(Progress... values) {
- super.onProgressUpdate(values);
- Data.backgroundTaskProgress.postValue(values[0]);
+ private void publishProgress(Progress progress) {
+ Data.backgroundTaskProgress.postValue(progress);
}
- @Override
- protected void onPostExecute(Result result) {
- super.onPostExecute(result);
+ private void finish(Result result) {
Progress progress = new Progress();
progress.setState(ProgressState.FINISHED);
progress.setError(result.error);
- onProgressUpdate(progress);
+ publishProgress(progress);
}
- @Override
- protected void onCancelled() {
- super.onCancelled();
+ private void cancel() {
Progress progress = new Progress();
progress.setState(ProgressState.FINISHED);
- onProgressUpdate(progress);
+ publishProgress(progress);
}
private void retrieveTransactionListLegacy(List<LedgerAccount> accounts,
List<LedgerTransaction> transactions)
@SuppressLint("DefaultLocale")
@Override
- protected Result doInBackground(Void... params) {
+ public void run() {
Data.backgroundTaskStarted();
List<LedgerAccount> accounts;
List<LedgerTransaction> transactions;
Data.lastUpdateDate.postValue(new Date());
- return new Result(null);
+ finish(new Result(null));
}
catch (MalformedURLException e) {
e.printStackTrace();
- return new Result("Invalid server URL");
+ finish(new Result("Invalid server URL"));
}
catch (HTTPException e) {
e.printStackTrace();
- return new Result(
- String.format("HTTP error %d: %s", e.getResponseCode(), e.getMessage()));
+ finish(new Result(
+ String.format("HTTP error %d: %s", e.getResponseCode(), e.getMessage())));
}
catch (IOException e) {
e.printStackTrace();
- return new Result(e.getLocalizedMessage());
+ finish(new Result(e.getLocalizedMessage()));
}
catch (RuntimeJsonMappingException e) {
e.printStackTrace();
- return new Result(Result.ERR_JSON_PARSER_ERROR);
+ finish(new Result(Result.ERR_JSON_PARSER_ERROR));
}
catch (ParseException e) {
e.printStackTrace();
- return new Result("Network error");
+ finish(new Result("Network error"));
}
catch (OperationCanceledException e) {
e.printStackTrace();
- return new Result("Operation cancelled");
+ finish(new Result("Operation cancelled"));
}
catch (ApiNotSupportedException e) {
e.printStackTrace();
- return new Result("Server version not supported");
+ finish(new Result("Server version not supported"));
}
finally {
Data.backgroundTaskFinished();
}
}
public void throwIfCancelled() {
- if (isCancelled())
+ if (isInterrupted())
throw new OperationCanceledException(null);
}
private enum ParserState {
package net.ktnx.mobileledger.async;
-import android.os.AsyncTask;
import android.util.Log;
import net.ktnx.mobileledger.db.Profile;
import net.ktnx.mobileledger.model.LedgerTransactionAccount;
import net.ktnx.mobileledger.utils.Globals;
import net.ktnx.mobileledger.utils.Logger;
+import net.ktnx.mobileledger.utils.Misc;
import net.ktnx.mobileledger.utils.NetworkUtil;
import net.ktnx.mobileledger.utils.SimpleDate;
import net.ktnx.mobileledger.utils.UrlEncodedFormData;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import static android.os.SystemClock.sleep;
import static net.ktnx.mobileledger.utils.Logger.debug;
/* TODO: get rid of the custom session/cookie and auth code?
* at which point the HTML form emulation can be dropped entirely
*/
-public class SendTransactionTask extends AsyncTask<LedgerTransaction, Void, Void> {
+public class SendTransactionTask extends Thread {
private final TaskCallback taskCallback;
private final Profile mProfile;
private final boolean simulate;
+ private final LedgerTransaction transaction;
protected String error;
private String token;
private String session;
- private LedgerTransaction transaction;
public SendTransactionTask(TaskCallback callback, Profile profile,
- boolean simulate) {
+ LedgerTransaction transaction, boolean simulate) {
taskCallback = callback;
mProfile = profile;
+ this.transaction = transaction;
this.simulate = simulate;
}
- public SendTransactionTask(TaskCallback callback, Profile profile) {
- taskCallback = callback;
- mProfile = profile;
- simulate = false;
- }
private void sendOK(API apiVersion) throws IOException, ApiNotSupportedException {
HttpURLConnection http = NetworkUtil.prepareConnection(mProfile, "add");
http.setRequestMethod("PUT");
}
}
@Override
- protected Void doInBackground(LedgerTransaction... ledgerTransactions) {
+ public void run() {
error = null;
try {
- transaction = ledgerTransactions[0];
-
final API profileApiVersion = API.valueOf(mProfile.getApiVersion());
switch (profileApiVersion) {
case auto:
error = e.getMessage();
}
- return null;
+ Misc.onMainThread(()->{
+ taskCallback.onTransactionSaveDone(error, transaction);
+ });
}
private void legacySendOkWithRetry() throws IOException {
int tried = 0;
tried++;
if (tried >= 2)
throw new IOException(String.format("aborting after %d tries", tried));
- sleep(100);
+ try {
+ sleep(100);
+ }
+ catch (InterruptedException e) {
+ e.printStackTrace();
+ break;
+ }
}
}
- @Override
- protected void onPostExecute(Void aVoid) {
- super.onPostExecute(aVoid);
- taskCallback.onTransactionSaveDone(error, transaction);
- }
-
}
\ No newline at end of file
package net.ktnx.mobileledger.async;
-import android.os.AsyncTask;
-
import net.ktnx.mobileledger.model.TransactionListItem;
import net.ktnx.mobileledger.ui.MainModel;
import net.ktnx.mobileledger.utils.Logger;
import java.util.Locale;
import java.util.Objects;
-public class TransactionDateFinder extends AsyncTask<TransactionDateFinder.Params, Void, Integer> {
- private MainModel model;
- @Override
- protected void onPostExecute(Integer pos) {
- model.foundTransactionItemIndex.setValue(pos);
+public class TransactionDateFinder extends Thread {
+ private final MainModel model;
+ private final SimpleDate date;
+ public TransactionDateFinder(MainModel model, SimpleDate date) {
+ this.model = model;
+ this.date = date;
}
@Override
- protected Integer doInBackground(Params... param) {
- this.model = param[0].model;
- SimpleDate date = param[0].date;
+ public void run() {
Logger.debug("go-to-date",
String.format(Locale.US, "Looking for date %04d-%02d-%02d", date.year, date.month,
date.day));
List<TransactionListItem> transactions = Objects.requireNonNull(
- param[0].model.getDisplayedTransactions()
- .getValue());
+ model.getDisplayedTransactions()
+ .getValue());
final int transactionCount = transactions.size();
Logger.debug("go-to-date",
String.format(Locale.US, "List contains %d transactions", transactionCount));
TransactionListItem target = new TransactionListItem(date, true);
int found =
Collections.binarySearch(transactions, target, new TransactionListItemComparator());
- if (found >= 0)
- return found;
- else
- return -1 - found;
- }
+ if (found < 0)
+ found = -1 - found;
- public static class Params {
- public final MainModel model;
- public final SimpleDate date;
- public Params(@NotNull MainModel model, @NotNull SimpleDate date) {
- this.model = model;
- this.date = date;
- }
+ model.foundTransactionItemIndex.postValue(found);
}
static class TransactionListItemComparator implements Comparator<TransactionListItem> {
package net.ktnx.mobileledger.ui;
-import android.os.AsyncTask;
-
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
}
Profile profile = Data.getProfile();
- retrieveTransactionsTask = new RetrieveTransactionsTask(this, profile);
+ retrieveTransactionsTask = new RetrieveTransactionsTask(profile);
Logger.debug("db", "Created a background transaction retrieval task");
- retrieveTransactionsTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ retrieveTransactionsTask.start();
}
public synchronized void stopTransactionsRetrieval() {
if (retrieveTransactionsTask != null)
- retrieveTransactionsTask.cancel(true);
+ retrieveTransactionsTask.interrupt();
else
Data.backgroundTaskProgress.setValue(null);
}
try {
SendTransactionTask saver =
- new SendTransactionTask(this, mProfile, model.getSimulateSaveFlag());
- saver.execute(tr);
+ new SendTransactionTask(this, mProfile, tr, model.getSimulateSaveFlag());
+ saver.start();
}
catch (Exception e) {
debug("new-transaction", "Unknown error: " + e);
package net.ktnx.mobileledger.ui.transaction_list;
-import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
@Override
public void onDatePicked(int year, int month, int day) {
RecyclerView list = requireActivity().findViewById(R.id.transaction_root);
- AsyncTask<TransactionDateFinder.Params, Void, Integer> finder = new TransactionDateFinder();
+ TransactionDateFinder finder = new TransactionDateFinder(model, new SimpleDate(year, month + 1, day));
- finder.execute(
- new TransactionDateFinder.Params(model, new SimpleDate(year, month + 1, day)));
+ finder.start();
}
}