Memory improvements

This commit is contained in:
serso 2016-01-24 23:40:56 +01:00
parent c000a525db
commit bd91238b14
12 changed files with 102 additions and 130 deletions

View File

@ -352,4 +352,15 @@ public final class App {
} }
return null; return null;
} }
@Nullable
public static String find(@Nonnull List<String> tokens, @Nonnull String text, int position) {
for (int i = 0; i < tokens.size(); i++) {
final String token = tokens.get(i);
if (text.startsWith(token, position)) {
return token;
}
}
return null;
}
} }

View File

@ -176,7 +176,7 @@ public class FunctionsRegistry extends BaseEntitiesRegistry<Function, OldFunctio
} }
@Override @Override
public synchronized void save() { public void save() {
handler.removeCallbacks(writeTask); handler.removeCallbacks(writeTask);
handler.postDelayed(writeTask, 500); handler.postDelayed(writeTask, 500);
} }

View File

@ -33,6 +33,9 @@ import javax.inject.Singleton;
@Singleton @Singleton
public class Keyboard { public class Keyboard {
@Nonnull
private final MathType.Result mathType = new MathType.Result();
@Inject @Inject
Editor editor; Editor editor;
@ -61,7 +64,7 @@ public class Keyboard {
int cursorPositionOffset = 0; int cursorPositionOffset = 0;
final StringBuilder textToBeInserted = new StringBuilder(text); final StringBuilder textToBeInserted = new StringBuilder(text);
final MathType.Result mathType = MathType.getType(text, 0, false); MathType.getType(text, 0, false, mathType);
switch (mathType.type) { switch (mathType.type) {
case function: case function:
textToBeInserted.append("()"); textToBeInserted.append("()");

View File

@ -26,34 +26,17 @@ import android.support.annotation.StringRes;
import jscl.math.operator.*; import jscl.math.operator.*;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public enum OperatorCategory implements Category { public enum OperatorCategory implements Category {
derivatives(100, R.string.derivatives) { my(R.string.c_fun_category_my) {
@Override
public boolean isInCategory(@Nonnull Operator operator) {
return operator instanceof Derivative || operator instanceof Integral || operator instanceof IndefiniteIntegral;
}
},
other(200, R.string.other) {
@Override
public boolean isInCategory(@Nonnull Operator operator) {
return operator instanceof Sum || operator instanceof Product;
}
},
my(0, R.string.c_fun_category_my) {
@Override @Override
public boolean isInCategory(@Nonnull Operator operator) { public boolean isInCategory(@Nonnull Operator operator) {
return !operator.isSystem(); return !operator.isSystem();
} }
}, },
common(50, R.string.c_fun_category_common) { common(R.string.c_fun_category_common) {
@Override @Override
public boolean isInCategory(@Nonnull Operator operator) { public boolean isInCategory(@Nonnull Operator operator) {
for (OperatorCategory category : values()) { for (OperatorCategory category : values()) {
@ -66,36 +49,29 @@ public enum OperatorCategory implements Category {
return true; return true;
} }
},
derivatives(R.string.derivatives) {
@Override
public boolean isInCategory(@Nonnull Operator operator) {
return operator instanceof Derivative || operator instanceof Integral || operator instanceof IndefiniteIntegral;
}
},
other(R.string.other) {
@Override
public boolean isInCategory(@Nonnull Operator operator) {
return operator instanceof Sum || operator instanceof Product;
}
}; };
private final int tabOrder;
@StringRes @StringRes
private final int title; private final int title;
OperatorCategory(int tabOrder, @StringRes int title) { OperatorCategory(@StringRes int title) {
this.tabOrder = tabOrder;
this.title = title; this.title = title;
} }
@Nonnull
public static List<OperatorCategory> getCategoriesByTabOrder() {
final List<OperatorCategory> result = Arrays.asList(OperatorCategory.values());
java.util.Collections.sort(result, new Comparator<OperatorCategory>() {
@Override
public int compare(OperatorCategory category, OperatorCategory category1) {
return category.tabOrder - category1.tabOrder;
}
});
// todo serso: current solution (as creating operators is not implemented yet)
result.remove(my);
return result;
}
public abstract boolean isInCategory(@Nonnull Operator operator); public abstract boolean isInCategory(@Nonnull Operator operator);
@Override @Override

View File

@ -26,7 +26,6 @@ import jscl.math.function.Function;
import jscl.math.function.IConstant; import jscl.math.function.IConstant;
import org.solovyev.android.calculator.math.MathType; import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.text.TextProcessor; import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.common.collections.Collections;
import org.solovyev.common.msg.MessageType; import org.solovyev.common.msg.MessageType;
import org.solovyev.common.search.StartsWithFinder; import org.solovyev.common.search.StartsWithFinder;
@ -56,20 +55,19 @@ public class ToJsclTextProcessor implements TextProcessor<PreparedExpression, St
@Nonnull @Nonnull
private static StringBuilder processExpression(@Nonnull String s) throws ParseException { private static StringBuilder processExpression(@Nonnull String s) throws ParseException {
final StartsWithFinder startsWithFinder = StartsWithFinder.newInstance(s);
final StringBuilder result = new StringBuilder(); final StringBuilder result = new StringBuilder();
final MathType.Results results = new MathType.Results();
MathType.Result mathTypeResult = null; MathType.Result mathTypeResult = null;
MathType.Result mathTypeBefore; MathType.Result mathTypeBefore = null;
final LiteNumberBuilder nb = new LiteNumberBuilder(Locator.getInstance().getEngine()); final LiteNumberBuilder nb = new LiteNumberBuilder(Locator.getInstance().getEngine());
for (int i = 0; i < s.length(); i++) { for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == ' ') continue; if (s.charAt(i) == ' ') continue;
startsWithFinder.setI(i);
results.release(mathTypeBefore);
mathTypeBefore = mathTypeResult == null ? null : mathTypeResult; mathTypeBefore = mathTypeResult == null ? null : mathTypeResult;
mathTypeResult = MathType.getType(s, i, nb.isHexMode(), results.obtain());
mathTypeResult = MathType.getType(s, i, nb.isHexMode());
nb.process(mathTypeResult); nb.process(mathTypeResult);
@ -84,7 +82,7 @@ public class ToJsclTextProcessor implements TextProcessor<PreparedExpression, St
if (mathTypeBefore != null && if (mathTypeBefore != null &&
(mathTypeBefore.type == MathType.function || mathTypeBefore.type == MathType.operator) && (mathTypeBefore.type == MathType.function || mathTypeBefore.type == MathType.operator) &&
App.find(MathType.groupSymbols, startsWithFinder) != null) { App.find(MathType.groupSymbols, s, i) != null) {
final String functionName = mathTypeBefore.match; final String functionName = mathTypeBefore.match;
final Function function = Locator.getInstance().getEngine().getFunctionsRegistry().get(functionName); final Function function = Locator.getInstance().getEngine().getFunctionsRegistry().get(functionName);
if (function == null || function.getMinParameters() > 0) { if (function == null || function.getMinParameters() > 0) {

View File

@ -26,49 +26,30 @@ import android.support.annotation.StringRes;
import jscl.math.function.IConstant; import jscl.math.function.IConstant;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public enum VarCategory implements Category { public enum VarCategory implements Category {
system(100, R.string.c_var_system) { my(R.string.c_var_my) {
@Override
public boolean isInCategory(@Nonnull IConstant var) {
return var.isSystem();
}
},
my(0, R.string.c_var_my) {
@Override @Override
public boolean isInCategory(@Nonnull IConstant var) { public boolean isInCategory(@Nonnull IConstant var) {
return !var.isSystem(); return !var.isSystem();
} }
},
system(R.string.c_var_system) {
@Override
public boolean isInCategory(@Nonnull IConstant var) {
return var.isSystem();
}
}; };
private final int tabOrder;
@StringRes @StringRes
private final int title; private final int title;
VarCategory(int tabOrder, @StringRes int title) { VarCategory(@StringRes int title) {
this.tabOrder = tabOrder;
this.title = title; this.title = title;
} }
@Nonnull
public static List<VarCategory> getCategoriesByTabOrder() {
final List<VarCategory> result = Arrays.asList(VarCategory.values());
java.util.Collections.sort(result, new Comparator<VarCategory>() {
@Override
public int compare(VarCategory category, VarCategory category1) {
return category.tabOrder - category1.tabOrder;
}
});
return result;
}
public abstract boolean isInCategory(@Nonnull IConstant var); public abstract boolean isInCategory(@Nonnull IConstant var);

View File

@ -242,7 +242,7 @@ public class History {
private void onRecentChanged(@Nonnull Object event) { private void onRecentChanged(@Nonnull Object event) {
handler.removeCallbacks(writeRecent); handler.removeCallbacks(writeRecent);
handler.postDelayed(writeRecent, 500); handler.postDelayed(writeRecent, 5000);
bus.post(event); bus.post(event);
} }

View File

@ -25,9 +25,9 @@ package org.solovyev.android.calculator.math;
import jscl.JsclMathEngine; import jscl.JsclMathEngine;
import jscl.NumeralBase; import jscl.NumeralBase;
import jscl.math.function.Constants; import jscl.math.function.Constants;
import org.solovyev.android.calculator.App;
import org.solovyev.android.calculator.Locator; import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.ParseException; import org.solovyev.android.calculator.ParseException;
import org.solovyev.common.JPredicate;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -259,55 +259,48 @@ public enum MathType {
*/ */
@Nonnull @Nonnull
public static Result getType(@Nonnull String text, int i, boolean hexMode) { public static Result getType(@Nonnull String text, int i, boolean hexMode) {
return getType(text, i, hexMode, new Result());
}
@Nonnull
public static Result getType(@Nonnull String text, int i, boolean hexMode, @Nonnull Result result) {
if (i < 0) { if (i < 0) {
throw new IllegalArgumentException("I must be more or equals to 0."); throw new IllegalArgumentException("I must be more or equals to 0.");
} else if (i >= text.length() && i != 0) { } else if (i >= text.length() && i != 0) {
throw new IllegalArgumentException("I must be less than size of text."); throw new IllegalArgumentException("I must be less than size of text.");
} else if (i == 0 && text.length() == 0) { } else if (i == 0 && text.length() == 0) {
return new Result(MathType.text, text); return result.set(MathType.text, text);
} }
final List<MathType> mathTypes = getMathTypesByPriority();
final StartsWithFinder startsWithFinder = new StartsWithFinder(text, i); for (int j = 0; j < mathTypes.size(); j++) {
final MathType mathType = mathTypes.get(j);
for (MathType mathType : getMathTypesByPriority()) { final String s = App.find(mathType.getTokens(), text, i);
final String s = find(mathType.getTokens(), startsWithFinder);
if (s == null) { if (s == null) {
continue; continue;
} }
if (s.length() > 1) { if (s.length() > 1) {
return new Result(mathType, s); return result.set(mathType, s);
} }
if (hexMode || JsclMathEngine.getInstance().getNumeralBase() == NumeralBase.hex) { if (hexMode || JsclMathEngine.getInstance().getNumeralBase() == NumeralBase.hex) {
final Character ch = s.charAt(0); final Character ch = s.charAt(0);
if (NumeralBase.hex.getAcceptableCharacters().contains(ch)) { if (NumeralBase.hex.getAcceptableCharacters().contains(ch)) {
return new Result(MathType.digit, s); return result.set(MathType.digit, s);
} }
} }
if (mathType == MathType.grouping_separator) { if (mathType == MathType.grouping_separator) {
if (i + 1 < text.length() && getType(text, i + 1, hexMode).type == MathType.digit) { if (i + 1 < text.length() && getType(text, i + 1, hexMode, result).type == MathType.digit) {
return new Result(mathType, s); return result.set(mathType, s);
} }
continue; continue;
} }
return new Result(mathType, s); return result.set(mathType, s);
} }
return new Result(MathType.text, text.substring(i)); return result.set(MathType.text, text.substring(i));
}
@Nullable
private static String find(@Nonnull List<String> list, @Nonnull JPredicate<String> predicate) {
for (int i = 0; i < list.size(); i++) {
final String token = list.get(i);
if(predicate.apply(token)) {
return token;
}
}
return null;
} }
@Nonnull @Nonnull
@ -388,15 +381,23 @@ public enum MathType {
public static class Result { public static class Result {
@Nonnull @Nonnull
public final MathType type; public MathType type;
@Nonnull @Nonnull
public final String match; public String match;
public Result(@Nonnull MathType type, @Nonnull String match) { public Result(@Nonnull MathType type, @Nonnull String match) {
this.type = type; set(type, match);
}
@Nonnull
Result set(@Nonnull MathType type, @Nonnull String match) {
this.type = type;
this.match = match; this.match = match;
return this;
}
public Result() {
} }
public int processToJscl(@Nonnull StringBuilder result, int i) throws ParseException { public int processToJscl(@Nonnull StringBuilder result, int i) throws ParseException {
@ -404,24 +405,23 @@ public enum MathType {
} }
} }
private static class StartsWithFinder implements JPredicate<String> { public static class Results {
@Nonnull
private final List<Result> list = new ArrayList<>();
@Nonnull @Nonnull
private final String targetString; public Result obtain() {
private int i; if (list.isEmpty()) {
return new Result();
public StartsWithFinder(@Nonnull String targetString, int i) { }
this.targetString = targetString; return list.remove(list.size() - 1);
this.i = i;
} }
@Override public void release(@Nullable Result result) {
public boolean apply(@Nullable String s) { if (result == null) {
return s != null && targetString.startsWith(s, i); return;
} }
list.add(result);
public void setI(int i) {
this.i = i;
} }
} }
} }

View File

@ -57,7 +57,7 @@ public class CalculatorVarsActivity extends BaseActivity implements CalculatorEv
final CalculatorFragmentType fragmentType = CalculatorFragmentType.variables; final CalculatorFragmentType fragmentType = CalculatorFragmentType.variables;
for (VarCategory category : VarCategory.getCategoriesByTabOrder()) { for (VarCategory category : VarCategory.values()) {
final Bundle fragmentParameters; final Bundle fragmentParameters;

View File

@ -47,7 +47,7 @@ public class OperatorsActivity extends BaseActivity implements CalculatorEventLi
final CalculatorFragmentType fragmentType = CalculatorFragmentType.operators; final CalculatorFragmentType fragmentType = CalculatorFragmentType.operators;
for (OperatorCategory category : OperatorCategory.getCategoriesByTabOrder()) { for (OperatorCategory category : OperatorCategory.values()) {
ui.addTab(this, fragmentType.createSubFragmentTag(category.name()), fragmentType.getFragmentClass(), BaseEntitiesFragment.createBundleFor(category.name()), category.title(), R.id.main_layout); ui.addTab(this, fragmentType.createSubFragmentTag(category.name()), fragmentType.getFragmentClass(), BaseEntitiesFragment.createBundleFor(category.name()), category.title(), R.id.main_layout);
} }
} }

View File

@ -42,25 +42,28 @@ public class FromJsclSimplifyTextProcessor implements TextProcessor<String, Gene
@Nonnull @Nonnull
@Override @Override
public String process(@Nonnull Generic from) { public String process(@Nonnull Generic from) {
return removeMultiplicationSigns(from.toString()); return fixMultiplicationSigns(from.toString());
} }
public String process(@Nonnull String s) { public String process(@Nonnull String s) {
return removeMultiplicationSigns(s); return fixMultiplicationSigns(s);
} }
@Nonnull @Nonnull
private String removeMultiplicationSigns(String s) { private String fixMultiplicationSigns(String s) {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
final MathType.Results results = new MathType.Results();
MathType.Result mathTypeBefore; MathType.Result mathTypeBefore = null;
MathType.Result mathType = null; MathType.Result mathType = null;
MathType.Result mathTypeAfter = null; MathType.Result mathTypeAfter = null;
for (int i = 0; i < s.length(); i++) { for (int i = 0; i < s.length(); i++) {
results.release(mathTypeBefore);
mathTypeBefore = mathType; mathTypeBefore = mathType;
if (mathTypeAfter == null) { if (mathTypeAfter == null) {
mathType = MathType.getType(s, i, false); mathType = MathType.getType(s, i, false, results.obtain());
} else { } else {
mathType = mathTypeAfter; mathType = mathTypeAfter;
} }
@ -68,7 +71,7 @@ public class FromJsclSimplifyTextProcessor implements TextProcessor<String, Gene
char ch = s.charAt(i); char ch = s.charAt(i);
if (ch == '*') { if (ch == '*') {
if (i + 1 < s.length()) { if (i + 1 < s.length()) {
mathTypeAfter = MathType.getType(s, i + 1, false); mathTypeAfter = MathType.getType(s, i + 1, false, results.obtain());
} else { } else {
mathTypeAfter = null; mathTypeAfter = null;
} }
@ -105,5 +108,4 @@ public class FromJsclSimplifyTextProcessor implements TextProcessor<String, Gene
return true; return true;
} }
} }

View File

@ -80,13 +80,14 @@ public class TextHighlighter implements TextProcessor<TextProcessorEditorResult,
final Engine engine = Locator.getInstance().getEngine(); final Engine engine = Locator.getInstance().getEngine();
final SpannableStringBuilder sb = new SpannableStringBuilder(); final SpannableStringBuilder sb = new SpannableStringBuilder();
final BaseNumberBuilder nb = !formatNumber ? new LiteNumberBuilder(engine) : new NumberBuilder(engine); final BaseNumberBuilder nb = !formatNumber ? new LiteNumberBuilder(engine) : new NumberBuilder(engine);
final MathType.Result result = new MathType.Result();
int offset = 0; int offset = 0;
int groupsCount = 0; int groupsCount = 0;
int openGroupsCount = 0; int openGroupsCount = 0;
for (int i = 0; i < text.length(); i++) { for (int i = 0; i < text.length(); i++) {
final MathType.Result result = MathType.getType(text, i, nb.isHexMode()); MathType.getType(text, i, nb.isHexMode(), result);
offset += nb.process(sb, result); offset += nb.process(sb, result);