I'm trying to do a change to a list in flutter, but it keeps giving me this error :
Concurrent modification during iteration: Instance(length:5) of '_GrowableList'.
I've searched and didn't find an answer or solution that fits the situation
Here I smy code:
void addProductsToCart() {
int addedAmount = cardNum * widget.currentProduct.price;
String note = noteTextController.text;
int total = cardNum * widget.currentProduct.price;
OrderItem orderItemInstance = OrderItem(
productName: widget.currentProduct.name,
productPrice: widget.currentProduct.price.toString(),
productQuantity: cardNum.toString(),
productNotes: note,
productSupplierName: widget.supplierName,
productImage: widget.currentProduct.image,
totalPrice: total.toString());
int theTotal = widget.cart.total;
if (widget.cart.orderDetails.length > 0){
for (var item in widget.cart.orderDetails){
if (item.productName == orderItemInstance.productName){
item.productQuantity += orderItemInstance.productQuantity;
item.totalPrice += orderItemInstance.totalPrice;
theTotal += addedAmount;
} else {
widget.cart.orderDetails.add(orderItemInstance);
theTotal += addedAmount;
}
}
} else {
theTotal += addedAmount;
widget.cart.orderDetails.add(orderItemInstance);
}
widget.cart.total += total;
setState(() {});
}
Based on the debugger in android studio . the error is being catched in one of the lines that adds or removes data from the list
Like this :
theTotal += addedAmount;
widget.cart.orderDetails.add(orderItemInstance);
I've solved it by delaying the add part after finishing the loop .. here is the working code :
void addProductsToCart() {
int addedAmount = cardNum * widget.currentProduct.price;
String note = noteTextController.text;
int total = cardNum * widget.currentProduct.price;
OrderItem orderItemInstance = OrderItem(
productName: widget.currentProduct.name,
productPrice: widget.currentProduct.price.toString(),
productQuantity: cardNum.toString(),
productNotes: note,
productSupplierName: widget.supplierName,
productImage: widget.currentProduct.image,
totalPrice: total.toString());
int theTotal = widget.cart.total;
List<OrderItem> toAdd= [];
if (widget.cart.orderDetails.length > 0){
for (var item in widget.cart.orderDetails){
if (item.productName == orderItemInstance.productName){
item.productQuantity += orderItemInstance.productQuantity;
item.totalPrice += orderItemInstance.totalPrice;
theTotal += addedAmount;
} else {
toAdd.add(orderItemInstance);
theTotal += addedAmount;
}
}
} else {
theTotal += addedAmount;
// widget.cart.orderDetails.add(orderItemInstance);
toAdd.add(orderItemInstance);
}
widget.cart.total += total;
toAdd.forEach((element) {
widget.cart.orderDetails.add(element);
});
setState(() {});
}
Related
I am using kotlin in my android app. I wrote following function for decoding coordinates :
private fun decodeCoordinates(address: String) {
var lat: String = ""
var lng: String = ""
var flag = true
var count = 0
while (count < address.length) {
if (address[count].equals(',')) {
flag = false;
continue
}
if (flag) {
lat += address[count]
} else {
lng += address[count]
}
count++;
}
Log.i("dxdiag", "Lat: $lat")
Log.i("dxdiag", "Lng: $lng")
}
but app hangs, if I remove continue , app does not hang
Issue is that you are changing the length of list inside the loop which leads to ANR. Use follinwg loop code:
var length = address.legth
while (count < length) {
if (address[count].equals(',')) {
flag = false;
continue
}
if (flag) {
lat += address[count]
} else {
lng += address[count]
}
count++;
}
This question already has answers here:
Convert String to operator(+*/-) in java
(5 answers)
Closed 4 years ago.
How I convert String containing Mathematic arithmetic operation's like "10 + 20 - 25", I am getting String from EditText,I want to convert get the Result of operation.
Here is my code to resolve your problem:
public class ExecuteHandler {
private static Character[] OPERATORS = { '/', '*', '+', '-' };
private static final String REGEXOPERATORS = "[/+,-,/*,//,-]";
private static final String REGEXDIGITS = "(\\d+)";
private ArrayList<Character> operators = new ArrayList<>();
private ArrayList<Integer> digits = new ArrayList<>();
public String execute(String math) {
StringBuilder result = new StringBuilder();
try {
getDigits(math);
getOperators(math);
getNextOperator(operators);
for (Integer digit : digits) {
result.append(String.valueOf(digit));
}
} catch (ArithmeticException | IndexOutOfBoundsException e) {
return "ERROR";
}
return result.toString().isEmpty() ? "ERROR" : result.toString();
}
public void clear() {
operators.clear();
digits.clear();
}
private void getNextOperator(ArrayList<Character> operators) {
for (Character op : OPERATORS) {
for (int i = 0; i < operators.size(); i++) {
if (operators.get(i) == '/') {
operators.remove(i);
digits.set(i, (digits.get(i) / digits.get(i + 1)));
digits.remove(i + 1);
i -= 1;
}
}
for (int i = 0; i < operators.size(); i++) {
if (operators.get(i) == '*') {
operators.remove(i);
digits.set(i, (digits.get(i) * digits.get(i + 1)));
digits.remove(i + 1);
i -= 1;
}
}
for (int i = 0; i < operators.size(); i++) {
if (operators.get(i) == '+') {
operators.remove(i);
digits.set(i, (digits.get(i) + digits.get(i + 1)));
digits.remove(i + 1);
i -= 1;
}
}
for (int i = 0; i < operators.size(); i++) {
if (operators.get(i) == '-') {
operators.remove(i);
digits.set(i, (digits.get(i) - digits.get(i + 1)));
digits.remove(i + 1);
i -= 1;
}
}
}
}
private void getDigits(String math) {
Pattern r = Pattern.compile(REGEXDIGITS);
Matcher m = r.matcher(math);
while (m.find()) {
int t = Integer.parseInt(math.substring(m.start(), m.end()));
digits.add(t);
}
}
private void getOperators(String math) {
Pattern r = Pattern.compile(REGEXOPERATORS);
Matcher m = r.matcher(math);
while (m.find()) {
operators.add(math.charAt(m.start()));
}
}
}
Call method execute with input is string like "10 + 20 - 25:", the result will be a string of value (if success) or ERROR (if any syntax error).
I try to unit test a method in my android project.
Everything works unit I try to set a value on a TextView.
Is it possible to skip one line of code or do I have to implement it as a UI Test?
This is the method I try to test:
public int compareEnteredValue(int batterySize, double valueFromEntry, double batteryArray[]) {
int output = 0;
for (int i = 0; i <= batteryArray.length - 1; i++) {
if (valueFromEntry >= batteryArray[i]) {
realChargeValue.setText((i * 5) + ""); // This is where the unit test fails
output = i*5;
}
if (valueFromEntry < batteryArray[batteryArray.length - 1]) {
realChargeValue.setText(R.string.hundredPercent);
output = 100;
}
}
return output;
}
You could break it down further. So that your unit does not set the text from within.
public int compareEnteredValue(int batterySize, double valueFromEntry, double batteryArray[]) {
int output = 0;
for (int i = 0; i <= batteryArray.length - 1; i++) {
if (valueFromEntry >= batteryArray[i]) {
//realChargeValue.setText((i * 5) + ""); // This is where the unit test fails
output = i*5;
}
if (valueFromEntry < batteryArray[batteryArray.length - 1]) {
//realChargeValue.setText(R.string.hundredPercent);
output = 100;
}
}
return output;
}
Then where you call the method..
int value = compareEnteredValue(....);
if(value == 100)
realChargeValue.setText(R.string.hundredPercent);
else
realChargeValue.setText(value + "");
You can then test the unit with no issue of the setText.
Adding to #Doomsknight answer, it is usually not required to Unit test every single line of your code. But in case you are passionate enough to test even to that level, here is how you can achieve it. I am using some added interfaces to showcase the testing.
public class TestableClass{
private UIElement realChargeValue;
public TestableClass(UIElement uiElem){
realChargeValue = uiElem;
}
public int compareEnteredValue(int batterySize, double valueFromEntry, double batteryArray[]) {
//Your method which needs to test realChargeValue
int output = 0;
for (int i = 0; i <= batteryArray.length - 1; i++) {
if (valueFromEntry >= batteryArray[i]) {
realChargeValue.setText((i * 5) + ""); // This is where the unit test fails
output = i*5;
}
if (valueFromEntry < batteryArray[batteryArray.length - 1]) {
realChargeValue.setText(R.string.hundredPercent);
output = 100;
}
}
return output;
}
}
public interface UIElement{
boolean setText();
}
For test class, you use as follows:
public class Test{
#Test
public void verify_compareEnteredValue_sets_correct_text(){
ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class);
UIElement dummyUIElement = mock(UIElement.class);
doReturn(true).when(dummyUIElement).setText(argumentCaptor.capture());
new TestableClass(dummyUIElement).compareEnteredValue();
List<String> expectedValues = argumentCaptor.getAllValues();
//do all asserts here over expectedValues
}
}
How to compare app version in android
I got latest version code and current version code , but the problem is
current version is 1.0
and latest version is 1.0.0
so how to compare that float value in android
I have written a small Android library for comparing version numbers: https://github.com/G00fY2/version-compare
What it basically does is this:
public int compareVersions(String versionA, String versionB) {
String[] versionTokensA = versionA.split("\\.");
String[] versionTokensB = versionB.split("\\.");
List<Integer> versionNumbersA = new ArrayList<>();
List<Integer> versionNumbersB = new ArrayList<>();
for (String versionToken : versionTokensA) {
versionNumbersA.add(Integer.parseInt(versionToken));
}
for (String versionToken : versionTokensB) {
versionNumbersB.add(Integer.parseInt(versionToken));
}
final int versionASize = versionNumbersA.size();
final int versionBSize = versionNumbersB.size();
int maxSize = Math.max(versionASize, versionBSize);
for (int i = 0; i < maxSize; i++) {
if ((i < versionASize ? versionNumbersA.get(i) : 0) > (i < versionBSize ? versionNumbersB.get(i) : 0)) {
return 1;
} else if ((i < versionASize ? versionNumbersA.get(i) : 0) < (i < versionBSize ? versionNumbersB.get(i) : 0)) {
return -1;
}
}
return 0;
}
This snippet doesn't offer any error checks or handling. Beside that my library also supports suffixes like "1.2-rc" > "1.2-beta".
I am a bit late to the party but I have a great solution for all of you!
1. Use this class:
public class VersionComparator implements Comparator {
public boolean equals(Object o1, Object o2) {
return compare(o1, o2) == 0;
}
public int compare(Object o1, Object o2) {
String version1 = (String) o1;
String version2 = (String) o2;
VersionTokenizer tokenizer1 = new VersionTokenizer(version1);
VersionTokenizer tokenizer2 = new VersionTokenizer(version2);
int number1, number2;
String suffix1, suffix2;
while (tokenizer1.MoveNext()) {
if (!tokenizer2.MoveNext()) {
do {
number1 = tokenizer1.getNumber();
suffix1 = tokenizer1.getSuffix();
if (number1 != 0 || suffix1.length() != 0) {
// Version one is longer than number two, and non-zero
return 1;
}
}
while (tokenizer1.MoveNext());
// Version one is longer than version two, but zero
return 0;
}
number1 = tokenizer1.getNumber();
suffix1 = tokenizer1.getSuffix();
number2 = tokenizer2.getNumber();
suffix2 = tokenizer2.getSuffix();
if (number1 < number2) {
// Number one is less than number two
return -1;
}
if (number1 > number2) {
// Number one is greater than number two
return 1;
}
boolean empty1 = suffix1.length() == 0;
boolean empty2 = suffix2.length() == 0;
if (empty1 && empty2) continue; // No suffixes
if (empty1) return 1; // First suffix is empty (1.2 > 1.2b)
if (empty2) return -1; // Second suffix is empty (1.2a < 1.2)
// Lexical comparison of suffixes
int result = suffix1.compareTo(suffix2);
if (result != 0) return result;
}
if (tokenizer2.MoveNext()) {
do {
number2 = tokenizer2.getNumber();
suffix2 = tokenizer2.getSuffix();
if (number2 != 0 || suffix2.length() != 0) {
// Version one is longer than version two, and non-zero
return -1;
}
}
while (tokenizer2.MoveNext());
// Version two is longer than version one, but zero
return 0;
}
return 0;
}
// VersionTokenizer.java
public static class VersionTokenizer {
private final String _versionString;
private final int _length;
private int _position;
private int _number;
private String _suffix;
private boolean _hasValue;
VersionTokenizer(String versionString) {
if (versionString == null)
throw new IllegalArgumentException("versionString is null");
_versionString = versionString;
_length = versionString.length();
}
public int getNumber() {
return _number;
}
String getSuffix() {
return _suffix;
}
public boolean hasValue() {
return _hasValue;
}
boolean MoveNext() {
_number = 0;
_suffix = "";
_hasValue = false;
// No more characters
if (_position >= _length)
return false;
_hasValue = true;
while (_position < _length) {
char c = _versionString.charAt(_position);
if (c < '0' || c > '9') break;
_number = _number * 10 + (c - '0');
_position++;
}
int suffixStart = _position;
while (_position < _length) {
char c = _versionString.charAt(_position);
if (c == '.') break;
_position++;
}
_suffix = _versionString.substring(suffixStart, _position);
if (_position < _length) _position++;
return true;
}
}
}
2. create this function
private fun isNewVersionAvailable(currentVersion: String, latestVersion: String): Boolean {
val versionComparator = VersionComparator()
val result: Int = versionComparator.compare(currentVersion, latestVersion)
var op = "=="
if (result < 0) op = "<"
if (result > 0) op = ">"
System.out.printf("%s %s %s\n", currentVersion, op, latestVersion)
return if (op == ">" || op == "==") {
false
} else op == "<"
}
3. and just call it by
e.g. isNewVersionAvailable("1.2.8","1.2.9") where 1.2.8 is your current version here and 1.2.9 is the latest version, which returns true!
Why overcomplicate this so much?
Just scale the major, minor, patch version and you have it covered:
fun getAppVersionFromString(version: String): Int { // "2.3.5"
val versions = version.split(".") // [2, 3, 5]
val major = versions[0].toIntOrDefault(0) * 10000 // 20000
val minor = versions[1].toIntOrDefault(0) * 1000 // 3000
val patch = versions[2].toIntOrDefault(0) * 100 // 500
return major + minor + patch // 2350
}
That way when you compare e.g 9.10.10 with 10.0.0 the second one is greater.
Use the following method to compare the versions number:
Convert float to String first.
public static int versionCompare(String str1, String str2) {
String[] vals1 = str1.split("\\.");
String[] vals2 = str2.split("\\.");
int i = 0;
// set index to first non-equal ordinal or length of shortest version string
while (i < vals1.length && i < vals2.length && vals1[i].equals(vals2[i])) {
i++;
}
// compare first non-equal ordinal number
if (i < vals1.length && i < vals2.length) {
int diff = Integer.valueOf(vals1[i]).compareTo(Integer.valueOf(vals2[i]));
return Integer.signum(diff);
}
// the strings are equal or one string is a substring of the other
// e.g. "1.2.3" = "1.2.3" or "1.2.3" < "1.2.3.4"
return Integer.signum(vals1.length - vals2.length);
}
Refer the following SO question : Efficient way to compare version strings in Java
i have string like these for example
309\306\308\337_338
309\306\337_338
310
311\315_316\336_337
311\315_316\336_337
311\335_336
these strings means list of page number , for example string "309\306\308\337_339" means
pages 309,306,308,337,338,339
i want to pass one of these string to function which return it as string like this
309,306,308,337,338,339
this function do that but in c# , i want to impalement in android
private static string Get_PageNumbers(string str)
{
ArrayList arrAll = new ArrayList();
MatchCollection match;
string[] excar;
string strid, firstNumber, lastlNumber;
int fn, ln;
ArrayList arrID = new ArrayList();
//***In Case The Range Number Between "_"
if (str.Contains("_"))
{
// match_reg = new Regex("(w?[\\d]+)*(_[\\d]+)");
Regex matchReg = new Regex("(w?[\\69]+_[\\d]+)*(q?[\\d]+//)*(a?[\\d]+_[\\d]+)*(y?[\\d]+)*");
match = matchReg.Matches(str);
int count = match.Count;
excar = new string[0];
for (int i = 0; i < count; i++)
{
Array.Resize(ref excar, count);
excar[i] = match[i].Groups[0].Value;
if (excar[i] != string.Empty)
arrID.Add(excar[i]);
}
//******IF Array Contains Range Of Number Like"102_110"
if (str.Contains("_"))
{
for (int i = 0; i < arrID.Count; i++)
{
strid = arrID[i].ToString();
if (arrID[i].ToString().Contains("_"))
{
int idy = strid.LastIndexOf("_");
firstNumber = strid.Substring(0, idy);
if (idy != -1)
{
lastlNumber = strid.Substring(idy + 1);
fn = int.Parse(firstNumber);
arrAll.Add(fn);
ln = int.Parse(lastlNumber);
for (int c = fn; c < ln; c++)
{
fn++;
arrAll.Add(fn);
}
}
}
else
{
arrAll.Add(arrID[i].ToString());
}
}
//******If Array Contain More Than One Number
if (arrAll.Count > 0)
{
str = "";
for (int i = 0; i < arrAll.Count; i++)
{
if (str != string.Empty)
str = str + "," + arrAll[i];
else
str = arrAll[i].ToString();
}
}
}
}
//***If string Contains between "/" only without "_"
else if (str.Contains("/") && !str.Contains("_"))
{
str = str.Replace("/", ",");
}
else if (str.Contains("\\"))
{
str = str.Replace("\\", ",");
}
return str;
}
I think this is easier to do with split function:
public static String Get_PageNumbers(String str) {// Assume str = "309\\306\\308\\337_338"
String result = "";
String[] pages = str.split("\\\\"); // now we have pages = {"309","306","308","337_338"}
for (int i = 0; i < pages.length; i++) {
String page = pages[i];
int index = page.indexOf('_');
if (index != -1) { // special case i.e. "337_338", index = 3
int start = Integer.parseInt(page.substring(0, index)); // start = 337
int end = Integer.parseInt(page.substring(index + 1)); // end = 338
for (int j = start; j <= end; j++) {
result += String.valueOf(j);
if (j != end) { // don't add ',' after last one
result += ",";
}
}
} else { // regular case i.e. "309","306","308"
result += page;
}
if (i != (pages.length-1)) { // don't add ',' after last one
result += ",";
}
}
return result; // result = "309,306,308,337,338"
}
For example this function when called as follows:
String result1 = Get_PageNumbers("309\\306\\308\\337_338");
String result2 = Get_PageNumbers("311\\315_316\\336_337");
String result3 = Get_PageNumbers("310");
Returns:
309,306,308,337,338
311,315,316,336,337
310
if i can suggest different implementation....
first, split string with "\" str.split("\\");, here you receive an array string with single number or a pattern like "num_num"
for all string founded, if string NOT contains "" char, put string in another array (othArr named), than, you split again with "" str.split("_");, now you have a 2 position array
convert that 2 strings in integer
now create a loot to min val form max val or two strings converted (and put it into othArr)
tranform othArr in a string separated with ","