I have a viewmodel that has a method. there are 4 conditions base on 4 Buttons that each condition can run separately by viewModelScope in this method.
Now I want to stop and restart each viewModelScope separately but I don't know how.
When I cancel the viewModelScope by job1.cancel(), I can't start it again.
This is my code that I want to handle that:
fun calculateDistance(tripId: Int) = viewModelScope.launch {
var currentCost: Double = 6500.0
var partCost: Double = 0.0
while (isActive) {
localRepository.getUnCalculatedLocation(tripId).collect { result ->
if (result.data!!.isNotEmpty()) {
result.data.forEach {
var passId = 0
val distance = Calculates.distance(
lat1 = if (it.latitude1 != 0.0) it.latitude1 else it.latitudeNet1,
lat2 = if (it.latitude2 != 0.0) it.latitude2 else it.latitudeNet2,
long1 = if (it.longitude1 != 0.0) it.longitude1 else it.longitudeNet1,
long2 = if (it.longitude2 != 0.0) it.longitude2 else it.longitudeNet2
)
localRepository.getPassId(it.tripId!!.toInt()).collect { id ->
if (id.data != null) {
passId = id.data
}
}
var passDistance = PassengerDistance(passId, distance)
_passDistance.postValue(passDistance)
localRepository.updateLocation(distance, it.id)
var uniqueId = ""
localRepository.getUniqueId(it.tripId).collect { uid ->
uniqueId = uid.data!!
}
when (passId) {
1 -> {
job1.launch {
_tripTime1.postValue(_tripTime1.value?.plus(2000))
if (distance == 0.0) {
if (secondCost1 < 10) secondCost1 += 2
else {
val expression: Expression =
Expression(_formula.value?.stoppingFormula)
val resultCost: EvaluationValue =
expression.with("T", secondCost1).evaluate()
currentCost =
if (_costPass1.value == null) constCost.toDouble() else _costPass1.value!!
partCost = resultCost.numberValue.toDouble()
_costPass1.postValue(resultCost.numberValue.toDouble() + currentCost)
secondCost1 = 0
}
} else {
val expression: Expression =
Expression(_formula.value?.movingFormula)
val resultCost: EvaluationValue =
expression.with("D", distance * 1000).evaluate()
val resultTest = (2109 / 200) * distance
currentCost =
if (_costPass1.value == null) constCost.toDouble() else _costPass1.value!!
partCost = resultCost.numberValue.toDouble()
var two = partCost * 2
Log.d(
"DISTANCE",
"actual cost is $partCost , Test: $resultTest"
)
_costPass1.postValue((resultCost.numberValue.toDouble() * 2) + currentCost)
_tripDistance1.postValue(
_tripDistance1.value?.plus(
distance
)
)
}
localRepository.updateCurrentCost(partCost, it.id!!)
val saveLocation = TripDetails(
id = it.id,
latitude1 = it.latitude1,
latitude2 = it.latitude2,
longitude1 = it.longitude1,
longitude2 = it.longitude2,
accuracy1 = it.accuracy1,
accuracy2 = it.accuracy2,
latitudeNet1 = it.latitudeNet1,
latitudeNet2 = it.latitudeNet2,
longitudeNet1 = it.longitudeNet1,
longitudeNet2 = it.longitudeNet2,
accuracy1Net = it.accuracy1Net,
accuracy2Net = it.accuracy2Net,
tripId = it.tripId,
distance = distance,
isCalculated = true,
isEnded = it.isEnded,
date = it.date,
cost = partCost,
uniqueId = uniqueId,
isMonitor = _isMonitor.value!!,
driverId = _driver.value?.data?.driverId!!
)
try {
repository.saveLocation(saveLocation).let { result ->
if (result.isSuccessful) {
Log.d("TAG", result.body()?.result.toString())
} else {
Log.d("TAG", result.body()?.message!!)
}
}
} catch (e: Exception) {
Log.d("Error", e.message.toString())
}
}
}
2 -> {
job2.launch {
_tripTime2.postValue(_tripTime2.value?.plus(2000))
if (distance == 0.0) {
if (secondCost2 < 10) secondCost2 += 2
else {
val expression: Expression =
Expression(_formula.value?.stoppingFormula)
val resultCost: EvaluationValue =
expression.with("T", secondCost2).evaluate()
currentCost =
if (_costPass2.value == null) constCost.toDouble() else _costPass2.value!!
_costPass2.postValue(resultCost.numberValue.toDouble() + currentCost)
partCost = resultCost.numberValue.toDouble()
secondCost2 = 0
}
} else {
val expression: Expression =
Expression(_formula.value?.movingFormula)
val resultCost: EvaluationValue =
expression.with("D", distance * 1000).evaluate()
currentCost =
if (_costPass2.value == null) constCost.toDouble() else _costPass2.value!!
_costPass2.postValue(resultCost.numberValue.toDouble() + currentCost)
partCost = resultCost.numberValue.toDouble()
_tripDistance2.postValue(_tripDistance2.value?.plus(distance))
}
val saveLocation = TripDetails(
id = it.id,
latitude1 = it.latitude1,
latitude2 = it.latitude2,
longitude1 = it.longitude1,
longitude2 = it.longitude2,
accuracy1 = it.accuracy1,
accuracy2 = it.accuracy2,
latitudeNet1 = it.latitudeNet1,
latitudeNet2 = it.latitudeNet2,
longitudeNet1 = it.longitudeNet1,
longitudeNet2 = it.longitudeNet2,
accuracy1Net = it.accuracy1Net,
accuracy2Net = it.accuracy2Net,
tripId = it.tripId,
distance = distance,
isCalculated = true,
isEnded = it.isEnded,
date = it.date,
cost = partCost,
uniqueId = uniqueId,
isMonitor = _isMonitor.value!!,
driverId = _driver.value?.data?.driverId!!
)
try {
repository.saveLocation(saveLocation).let { result ->
if (result.isSuccessful) {
Log.d("TAG", result.body()?.result.toString())
} else {
Log.d("TAG", result.body()?.message!!)
}
}
} catch (e: Exception) {
Log.d("Error", e.message.toString())
}
}
}
3 -> {
job3.launch {
_tripTime3.postValue(_tripTime3.value?.plus(2000))
if (distance == 0.0) {
if (secondCost3 < 10) secondCost3 += 2
else {
val expression: Expression =
Expression(_formula.value?.stoppingFormula)
val resultCost: EvaluationValue =
expression.with("T", secondCost3).evaluate()
currentCost =
if (_costPass3.value == null) constCost.toDouble() else _costPass3.value!!
_costPass3.postValue(resultCost.numberValue.toDouble() + currentCost)
partCost = resultCost.numberValue.toDouble()
secondCost3 = 0
}
} else {
val expression: Expression =
Expression(_formula.value?.movingFormula)
val resultCost: EvaluationValue =
expression.with("D", distance * 1000).evaluate()
currentCost =
if (_costPass3.value == null) constCost.toDouble() else _costPass3.value!!
_costPass3.postValue(resultCost.numberValue.toDouble() + currentCost)
partCost = resultCost.numberValue.toDouble()
_tripDistance3.postValue(_tripDistance3.value?.plus(distance))
}
val saveLocation = TripDetails(
id = it.id,
latitude1 = it.latitude1,
latitude2 = it.latitude2,
longitude1 = it.longitude1,
longitude2 = it.longitude2,
accuracy1 = it.accuracy1,
accuracy2 = it.accuracy2,
latitudeNet1 = it.latitudeNet1,
latitudeNet2 = it.latitudeNet2,
longitudeNet1 = it.longitudeNet1,
longitudeNet2 = it.longitudeNet2,
accuracy1Net = it.accuracy1Net,
accuracy2Net = it.accuracy2Net,
tripId = it.tripId,
distance = distance,
isCalculated = true,
isEnded = it.isEnded,
date = it.date,
cost = partCost,
uniqueId = uniqueId,
isMonitor = _isMonitor.value!!,
driverId = _driver.value?.data?.driverId!!
)
try {
repository.saveLocation(saveLocation).let { result ->
if (result.isSuccessful) {
Log.d("TAG", result.body()?.result.toString())
} else {
Log.d("TAG", result.body()?.message!!)
}
}
} catch (e: Exception) {
Log.d("Error", e.message.toString())
}
}
}
4 -> {
job4.launch {
_tripTime4.postValue(_tripTime4.value?.plus(2000))
if (distance == 0.0) {
if (secondCost4 < 10) secondCost4 += 2
else {
val expression: Expression =
Expression(_formula.value?.stoppingFormula)
val resultCost: EvaluationValue =
expression.with("T", secondCost4).evaluate()
currentCost =
if (_costPass4.value == null) constCost.toDouble() else _costPass4.value!!
_costPass4.postValue(resultCost.numberValue.toDouble() + currentCost)
partCost = resultCost.numberValue.toDouble()
secondCost4 = 0
}
} else {
val expression: Expression =
Expression(_formula.value?.movingFormula)
val resultCost: EvaluationValue =
expression.with("D", distance * 1000).evaluate()
currentCost =
if (_costPass4.value == null) constCost.toDouble() else _costPass4.value!!
_costPass4.postValue(resultCost.numberValue.toDouble() + currentCost)
partCost = resultCost.numberValue.toDouble()
_tripDistance4.postValue(_tripDistance4.value?.plus(distance))
}
val saveLocation = TripDetails(
id = it.id,
latitude1 = it.latitude1,
latitude2 = it.latitude2,
longitude1 = it.longitude1,
longitude2 = it.longitude2,
accuracy1 = it.accuracy1,
accuracy2 = it.accuracy2,
latitudeNet1 = it.latitudeNet1,
latitudeNet2 = it.latitudeNet2,
longitudeNet1 = it.longitudeNet1,
longitudeNet2 = it.longitudeNet2,
accuracy1Net = it.accuracy1Net,
accuracy2Net = it.accuracy2Net,
tripId = it.tripId,
distance = distance,
isCalculated = true,
isEnded = it.isEnded,
date = it.date,
cost = partCost,
uniqueId = uniqueId,
isMonitor = _isMonitor.value!!,
driverId = _driver.value?.data?.driverId!!
)
try {
repository.saveLocation(saveLocation).let { result ->
if (result.isSuccessful) {
Log.d("TAG", result.body()?.result.toString())
} else {
Log.d("TAG", result.body()?.message!!)
}
}
} catch (e: Exception) {
Log.d("Error", e.message.toString())
}
}
}
}
}
}
}
delay(2000)
}
}
Here there is a when statement that has 4 conditions. There are 4 Buttons for each conditions.
The a
The code is complicated. It's hard to understand the workflow.
If you want to run a new job for the phase and cancel it for some reason.
You have to create a new Job for each phase.
1 -> {
job1 = viewModelScope.launch {
...
4 -> {
job4 = viewModelScope.launch {
UPDATE based on comments:
In your code you define variables:
val job1 = viewModelScope
val job2 = viewModelScope
...
This is not a job definition, this is just a new variables with reference to the viewModelScope.
So when you call job1.cancel() it equals to call viewModelScope.cancel(). The result the viewModelScope is canceled and no coroutine can be started.
To change it you can refactor your code to use a job:
#field:Volatile
var job1: Job? = null
#field:Volatile
var job2: Job? = null
...
Create a new job for the each phase in fun calculateDistance(tripId: Int):
1 -> {
job1 = viewModelScope.launch {
2 -> {
job2 = viewModelScope.launch {
To cancel a job in the other code you have to use the following code:
job1?.cancel()
Related
I am trying to remove some Unknown tags (C3, BF40, C2,.. etc) from ByteArray using TLVUtility (mastercard class from terminalSdk-2.0.3.jar), Tags was not removing from the ByteArray. I am trying like this,
Here is my TLV Data I have,
ppseResponse = ByteUtility.hexStringToByteArray("6F54840E325041592E5359532E4444463031C30F4920414D2054484520424553542033BF4003C20101A52BBF0C28610C4F07A0000000041010870101610C4F07A0000000043060870103610A4F05B0123456788701099000")
I am trying this to remove the Unknown tags like,
"BEFORE << ${ByteUtility.byteArrayToHexString(ppseResponse)}".toLog(activity, TAG) //To print Log
val unknownTags = byteArrayOf((0x00C3).toByte(),(0xBF40).toByte(), (0x00C2).toByte())
var removed = TLVUtility.removeTag(ppseResponse, ContentType.TLV,unknownTags)
"AFTER << ${ByteUtility.byteArrayToHexString(removed)}".toLog(activity, TAG) //To print Log
Here is the function removeTag on terminalSdk-2.0.3.jar function look likes,
public static byte[] removeTag(byte[] var0, ContentType var1, byte[] var2) {
int var10000;
Throwable var10001;
String var28;
label698: {
var10000 = 2 % 2;
if (var0 != null) {
label691: {
var10000 = g + 85;
f = var10000 % 128;
if (var10000 % 2 == 0) {
byte[] var26 = var2;
byte var27;
label676: {
label675: {
try {
null.hashCode();
if (var26 == null) {
break label675;
}
} catch (Throwable var25) {
throw var25;
}
var27 = 42;
break label676;
}
var27 = 74;
}
switch(var27) {
case 42:
break;
case 74:
default:
break label691;
}
} else if (var2 == null) {
break label691;
}
var10000 = f + 55;
g = var10000 % 128;
switch(var10000 % 2 != 0 ? 0 : 1) {
case 0:
default:
if (var2.length >= 1) {
break label698;
}
break;
case 1:
if (var2.length >= 1) {
break label698;
}
}
}
}
var28 = e(31, '卆', 490).intern();
try {
((Class)q.b(38, 8595, '\ue0f7')).getMethod("e", String.class).invoke((Object)null, var28);
} catch (Throwable var22) {
var10001 = var22.getCause();
if (var10001 != null) {
throw var10001;
}
throw var22;
}
throw new LibraryUncheckedException(ExceptionCode.X6F44);
}
label700: {
if (var1 == ContentType.T) {
var10000 = g + 15;
f = var10000 % 128;
if (var10000 % 2 == 0) {
if (var0.length < 0) {
break label700;
}
} else if (var0.length < 1) {
break label700;
}
}
switch(var1 != ContentType.TLV ? 81 : 64) {
case 81:
if (var1 != ContentType.TDO) {
break;
}
case 64:
default:
if (var0.length < 3) {
var28 = e(47, '\u0000', 560).intern();
try {
((Class)q.b(38, 8595, '\ue0f7')).getMethod("e", String.class).invoke((Object)null, var28);
} catch (Throwable var23) {
var10001 = var23.getCause();
if (var10001 != null) {
throw var10001;
}
throw var23;
}
throw new LibraryUncheckedException(ExceptionCode.X6F43);
}
}
ArrayList var3 = conditionalTlvParsing(var0, var1, e(1, '\u0000', 140).intern(), true);
Iterator var4 = var3.iterator();
while(var4.hasNext()) {
BerTlv var5 = (BerTlv)var4.next();
switch(var5.getTagObject().getNTag() == ByteUtility.byteArrayToInt(var2) ? 39 : 84) {
case 39:
default:
var4.remove();
case 84:
}
}
return formByteArrayFromTlvList(var3, var1);
}
var28 = e(39, '\u0000', 521).intern();
try {
((Class)q.b(38, 8595, '\ue0f7')).getMethod("e", String.class).invoke((Object)null, var28);
} catch (Throwable var24) {
var10001 = var24.getCause();
if (var10001 != null) {
throw var10001;
}
throw var24;
}
throw new LibraryUncheckedException(ExceptionCode.X6F43);
}
I fixed this issue by creating new custom function. Here is the function. Now on this function I am removing all the Unknown Tags and its Skipping all Known Tags and Third party data and Optional Tags Tags
First we need to define optional Tag,
private var optionalTags: ArrayList<ByteArray> = getOptionalTags()
Here is the function I am adding Optional Tags,
private fun getOptionalTags(): ArrayList<ByteArray> {
optionalTags = ArrayList()
optionalTags.add(ByteUtility.hexStringToByteArray("9F3E")) //Terminal Categories Supported List
optionalTags.add(ByteUtility.hexStringToByteArray("9F3F")) //Selection Data Object List
optionalTags.add(ByteUtility.hexStringToByteArray("9F2A")) //Kernel Identifier
optionalTags.add(ByteUtility.hexStringToByteArray("9F0A")) //Application Selection Registered Proprietary Data
return optionalTags
}
Here is the function to remove the Unknown tags,
private fun removeUnknownTags(ppseResponse: ByteArray): ByteArray {
var parentTags: MutableMap<ByteArray, Int> = LinkedHashMap()
var ppseResp = ppseResponse;
var i = 0
"PPSE (Length: ${ppseResp.size}) : HexString: ${ByteUtility.byteArrayToHexString(ppseResp)} \n ByteArray: ${ppseResp.toList()}".toLog()
while (i < ppseResp.size - 1) {
var removeTag = false;
var currentTag = TLVUtility.getCurrentTag(ppseResp, i);
var nextIndex = i + currentTag.size;
var tLVLengthInfo = TLVUtility.getTLVLengthInfo(ppseResp, nextIndex);
val tagLength = tLVLengthInfo.expectedNumberOfBytes
var tagValueSize = tLVLengthInfo.lengthBytes.size
var tagValue = ByteUtility.getSubByteArray(ppseResp, nextIndex + tagValueSize, tagLength)
"<==- ${i} : ${ByteUtility.byteArrayToHexString(currentTag)} (${TLVUtility.getReferenceTagDetails(currentTag).name}) , Length:${tagLength} (${tLVLengthInfo.lengthBytes.toList()} : ${ByteUtility.byteArrayToHexString(tLVLengthInfo.lengthBytes)}) , Max:${TLVUtility.getReferenceTagDetails(currentTag).maxLen} , Min:${TLVUtility.getReferenceTagDetails(currentTag).minLen} -==>".toLog()
"Value : ${ByteUtility.byteArrayToHexString(tagValue)} , Bytes:${tagValue.toList()}".toLog()
var tagNameLengthValue = ByteUtility.getSubByteArray(ppseResp, i, currentTag.size + tagValueSize + tagLength)
if (TLVUtility.getReferenceTagDetails(currentTag).name.contentEquals("Unknown Tag")) {
var optionalTag = false;
for (optTag in optionalTags) {
if (currentTag.contentEquals(optTag)) {
"${ByteUtility.byteArrayToHexString(currentTag)} is Optional Tag".toLog()
i = nextIndex + tagValueSize + tagLength;
optionalTag = true;
break
}
}
if (!optionalTag)
removeTag = true
} else if (TLVUtility.getReferenceTagDetails(currentTag).name.contentEquals("Third Party Data")) {
i = nextIndex + tagValueSize + tagLength;
} else {
if (!removeTag) {
if (TLVUtility.isTLVEncoded(tagValue)) {
parentTags.put(currentTag, i)
parentTags.entries.stream()
.sorted(Map.Entry.comparingByValue<ByteArray, Int>().reversed())
.forEachOrdered { x -> parentTags.put(x.key, x.value) }
if (tagValue.contentEquals(ByteUtility.hexStringToByteArray("00"))) {
i = nextIndex + tagValueSize + tagLength;
} else
i = nextIndex + tagValueSize
} else {
i = nextIndex + tagValueSize + tagLength;
}
}
}
if (removeTag) {
"-*-*-*-Removing TAG ${ByteUtility.byteArrayToHexString(currentTag)}-*-*-*-".toLog()
ppseResp = ByteUtility.getSubByteArray(ppseResp, 0, i) + ByteUtility.getSubByteArray(ppseResp, i + tagNameLengthValue.size)
var byteDiff = tagNameLengthValue.size
"--Updating Tag Length (Removed Bytes ${byteDiff})--".toLog()
for (tag in parentTags.entries.reversed()) {
var parentBytes = tag.key
var index = tag.value
var sizeIndex = index + parentBytes.size
var unknownTLVLengthInfo = TLVUtility.getTLVLengthInfo(ppseResp, sizeIndex);
val length = unknownTLVLengthInfo.expectedNumberOfBytes
if (i > index && i <= index + length) { //To Check is Parent Tag
"Parent Tag ${ByteUtility.byteArrayToHexString(tag.key)} (Bytes:${tag.key.toList()}) , Position:${tag.value}".toLog()
var lengthByteArray = unknownTLVLengthInfo.lengthBytes
var newLengthByteArray = ByteUtility.intToBerEncodedLength(length - byteDiff).bytes
var lengthDiff = lengthByteArray.size - newLengthByteArray.size;
byteDiff = byteDiff + lengthDiff
ppseResp = ByteUtility.getSubByteArray(ppseResp, 0, sizeIndex) + newLengthByteArray + ByteUtility.getSubByteArray(ppseResp, sizeIndex + lengthByteArray.size)
if (lengthDiff > 0) {
i = i - lengthDiff
for (child in parentTags.entries) {
if (child.value > tag.value) {
parentTags.replace(child.key, child.value - lengthDiff)
}
}
}
// "PPSE After (Length: ${ppseResp.size}): ${ByteUtility.byteArrayToHexString(ppseResp)} \n ByteArray: ${ppseResp.toList()}".toLog()
}
}
}
}
return ppseResp;
}
I have a Lottie json file, I play it with ValueAnimator after loaded in SurfaceView's LottieDrawable. But images are not showing, the animation is running without images!
But when I tested this json in LottieAnimationView, It just works fine. So what should I do to play in LottieDrawable? thx
LottieDrawable, play without images showing:
if (lottieDrawable.composition == null) {
//val url = "https://assets4.lottiefiles.com/packages/lf20_dkzdaf1z.json"
//val task = LottieCompositionFactory.fromUrl(applicationContext, url)
val input = applicationContext.assets.open("wallpaper_lottie.json")
val task = LottieCompositionFactory.fromJsonInputStream(input, null)
//val input = applicationContext.assets.open("wallpaper_lottie.zip")
//val zip = ZipInputStream(input)
//val task = LottieCompositionFactory.fromZipStream(zip, null)
task.addFailureListener {
Log.i(TAG, "LOT::addFailureListener, " + it.message)
}
task.addListener { comp ->
// lottie drawable
lottieDrawable.composition = comp
Log.i(TAG, "LOT::lottieDrawable.composition, 1 = ${lottieDrawable.composition.toString().subSequence(0, 15)}")
val lotDrawableWidth = (screenWidth * 90F / 100F).toInt()
val lotDrawableHeight = (screenWidth * 80F / 100F).toInt()
val statusBarHeight = 65
val lotDrawableLeft = ((screenWidth - lotDrawableWidth) / 2).toInt()
val lotDrawableTop = (screenHeight - statusBarHeight).toInt()
lottieDrawable.bounds = Rect(
lotDrawableLeft,
lotDrawableTop,
lotDrawableLeft + lotDrawableWidth,
lotDrawableTop + lotDrawableHeight,
)
// lottie animator
lottieAnimator.cancel()
lottieAnimator.setIntValues(0, lottieDrawable.maxFrame.toInt())
lottieAnimator.repeatCount = LottieDrawable.INFINITE
lottieAnimator.duration = 6000
lottieAnimator.addUpdateListener { anim ->
val frame = anim.animatedValue as Int
lottieDrawable.frame = frame
// lottieDrawable.draw(canvas)
Log.i(TAG, "LOT::addUpdateListener, frame = ${lottieDrawable.frame}")
}
lottieAnimator.start()
}
}
LottieAnimationView, play with image showed:
<com.airbnb.lottie.LottieAnimationView
android:id="#+id/iv_scanning"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
app:lottie_fileName="wallpaper_lottie.json"
app:lottie_loop="true"
/>
Finally I play it using ValueAnimator, and FakeAnimView did the trick. Wish to help:
fun draw() {
val screenWidth = canvas.width.toFloat()
val screenHeight = canvas.height.toFloat()
// draw lottie drawable
// https://github.com/airbnb/lottie-android/issues/1177
if (lottieDrawable.composition == null) {
val input = applicationContext.assets.open("anim/lottie.json")
val task = LottieCompositionFactory.fromJsonInputStream(input, null)
task.addFailureListener {
if (BuildConfig.DEBUG) {
Log.i(TAG, "LOT::drawPreview, addFailureListener, " + it.message)
}
}
task.addListener { comp ->
// lottie drawable
lottieDrawable.composition = comp
val lotDrawableWidth = (screenWidth * 80F / 100F).toInt()
val lotDrawableHeight = (screenWidth * 60F / 100F).toInt()
val statusBarHeight = if (Sdk30PermissionUtil.hasSdk30()) 0F else 65F
val lotDrawableLeft = ((screenWidth - lotDrawableWidth) / 2).toInt()
val lotDrawableTop = (screenHeight - statusBarHeight).toInt()
lottieDrawable.bounds = Rect(
lotDrawableLeft,
lotDrawableTop,
lotDrawableLeft + lotDrawableWidth,
lotDrawableTop + lotDrawableHeight,
)
// lottie animator
lottieAnimator.cancel()
lottieAnimator.setIntValues(0, lottieDrawable.maxFrame.toInt())
lottieAnimator.repeatCount = LottieDrawable.INFINITE
lottieAnimator.duration = 6000
lottieAnimator.addUpdateListener { anim ->
val frame = anim.animatedValue as Int
lottieDrawable.frame = frame
if (BuildConfig.DEBUG) {
Log.i(TAG, "LOT::lottieAnimator.addUpdateListener, frame = ${lottieDrawable.frame}")
}
}
lottieAnimator.start()
ReleaseUtil.release(input) //! prevent OOM
}
}
if (lottieDrawable.composition != null) {
if (BuildConfig.DEBUG) {
Log.i(TAG, "drawPreview, setDelegate")
}
WallpaperUtil.setDelegate(applicationContext, lottieDrawable)
// draw lottie drawable
val lotDrawableWidth = (screenWidth * 80F / 100F).toInt()
val lotDrawableHeight = lotDrawableWidth
val transX = (screenWidth - lotDrawableWidth) / 2
val transY = 365F
canvas.translate(transX, transY)
lottieDrawable.draw(canvas)
}
}
fun setDelegate(context: Context, lottieDrawable: LottieDrawable) {
try {
if (BuildConfig.DEBUG) {
Log.i(TAG, "setDelegate")
Log.i(TAG, "setDelegate, lottieDrawable.getCallback = " + lottieDrawable.callback)
}
if (lottieDrawable.callback == null) {
lottieDrawable.callback = FakeAnimView(context, null)
}
lottieDrawable.setImageAssetDelegate { asset: LottieImageAsset ->
var bitmap: Bitmap? = null
try {
val filePath = "anim/images/"
val fileName = asset.fileName
bitmap = getBitmapFromAsset(context, filePath + fileName)
if (BuildConfig.DEBUG) {
Log.i(TAG, "setDelegate, fileName=$fileName")
Log.i(TAG, "setDelegate, bitmap=$bitmap")
}
} catch (t: Throwable) {
t.printStackTrace()
Log.i(TAG, "setDelegate, Throwable = $t")
}
bitmap
}
} catch (t: Throwable) {
t.printStackTrace()
Log.i(TAG, "setDelegate, Throwable = $t")
}
}
/* loaded from: classes2.dex */
public class FakeAnimView extends View {
public FakeAnimView(Context context, #Nullable AttributeSet attributeSet) {
super(context, null);
}
#Override // android.view.View
public int getVisibility() {
return VISIBLE;
}
#Override // android.view.View
protected void onMeasure(int i2, int i3) {
super.onMeasure(200, 200);
}
}
I want update progress bar in parent activity where recycler view is located.when user clicked on each radio buttons add a number to progress bar I have done it but I don't know how can I pass data from recycler view adapter to parent activity.
enter image description here
class MbtiQuestionAdapter(val questionList: QuestionList) :
RecyclerView.Adapter<QuestionViewHolder>() {
var maps = arrayListOf<HashMap<String, String>>()
var i = 0
var e = 0
var n = 0
var t = 0
var j = 0
var p = 0
var f = 0
var s = 0
var typeQuestion = ""
var testnumbers = 0
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QuestionViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val cellForRow = layoutInflater.inflate(
AminAmix.com.socialpersonality.R.layout.question_row,
parent,
false
)
return QuestionViewHolder(cellForRow)
}
#SuppressLint("ResourceAsColor")
override fun onBindViewHolder(holder: QuestionViewHolder, position: Int) {
//val question = questions.get(position)
if (questionList.questions[position].tip != "") {
holder.view.txtTitletipsQuestionRow.visibility = View.VISIBLE
// holder.view.imgtips.visibility = View.VISIBLE
holder.view.txtTipsQuestion.visibility = View.VISIBLE
holder.view.txtTipsQuestion.text = questionList.questions[position].tip
} else {
holder.view.imageView15.visibility = View.INVISIBLE
holder.view.shapeBlue.visibility = View.VISIBLE
holder.view.shapeGreen.visibility = View.VISIBLE
holder.view.shapeCircle.visibility = View.VISIBLE
}
holder.view.txtAmountQuestion.text = questionList.questions.size.toString()
holder.view.txtCurrentQuestion.text = (position + 1).toString()
val question = questionList.questions.get(position).title
Log.i("Position", position.toString())
val answers = questionList.questions.get(position).answers
var valueOfRadio = ""
if (questionList.questions.get(position).type == "range") {
holder.view.cardAB.visibility = View.INVISIBLE
for (answer in answers) {
val value = answer.value
typeQuestion = answer.title
Log.i("Position2", value.toString())
if (answer.title == "Agree") {
holder.view.txtQuestionDisAgree.text = answer.title
} else {
holder.view.txtQuestionAgree.text = answer.title
}
}
holder.view.radioGroup.setOnCheckedChangeListener { group, checkedId ->
if (checkedId == AminAmix.com.socialpersonality.R.id.radioButton_middle) {
Log.i("Radio", "0")
valueOfRadio = "0"
}
if (checkedId == AminAmix.com.socialpersonality.R.id.radioButton_agree1) {
Log.i("Radio", "1")
valueOfRadio = "1"
}
if (checkedId == AminAmix.com.socialpersonality.R.id.radioButton_agree2) {
Log.i("Radio", "2")
valueOfRadio = "2"
}
if (checkedId == AminAmix.com.socialpersonality.R.id.radioButton_disagree1) {
Log.i("Radio", "-1")
valueOfRadio = "-1"
}
if (checkedId == AminAmix.com.socialpersonality.R.id.radioButton_disagree_2) {
Log.i("Radio", "-2")
valueOfRadio = "-2"
}
val checked = group.findViewById(checkedId) as RadioButton
val list: ArrayList<String> = ArrayList()
list.add(checked.getText().toString())
Log.i("Chekkk", list.toString())
Log.i(
"checkedId", position.toString()
)
var idIf = ""
var typeIf = ""
var testValue = 0
var map = HashMap<String, String>();
var radioInt = valueOfRadio.toInt()
var selectedAnswers = questionList.questions[position].answers
if (radioInt > 0) {
for (answer in selectedAnswers) {
if (answer.title == "Agree") {
typeIf = answer.type
testValue = answer.value
holder.view.txtQuestionDisAgree.setTextColor(Color.parseColor("#5E5E5E"));
holder.view.txtQuestionAgree.setTextColor(Color.parseColor("#B2B2B2"));
holder.view.txtCurrentQuestion.setTextColor(Color.parseColor("#0B6095"));
holder.view.txtAmountQuestion.setTextColor(Color.parseColor("#0B6095"));
holder.view.txtCurrentQuestion2.setTextColor(Color.parseColor("#0B6095"));
holder.view.txtTitleQuestions.setTextColor(Color.parseColor("#0B6095"));
holder.view.questionsTik.visibility = View.VISIBLE
}
}
} else if (radioInt < 0) {
for (answer in selectedAnswers) {
if (answer.title == "Disagree") {
typeIf = answer.type
testValue = answer.value
holder.view.txtQuestionAgree.setTextColor(Color.parseColor("#5E5E5E"));
holder.view.txtQuestionDisAgree.setTextColor(Color.parseColor("#B2B2B2"));
holder.view.txtCurrentQuestion.setTextColor(Color.parseColor("#0B6095"));
holder.view.txtAmountQuestion.setTextColor(Color.parseColor("#0B6095"));
holder.view.txtCurrentQuestion2.setTextColor(Color.parseColor("#0B6095"));
holder.view.txtTitleQuestions.setTextColor(Color.parseColor("#0B6095"));
holder.view.questionsTik.visibility = View.VISIBLE
}
}
} else {
holder.view.txtQuestionAgree.setTextColor(Color.parseColor("#B2B2B2"));
holder.view.txtQuestionDisAgree.setTextColor(Color.parseColor("#B2B2B2"));
holder.view.txtCurrentQuestion.setTextColor(Color.parseColor("#0B6095"));
holder.view.txtAmountQuestion.setTextColor(Color.parseColor("#0B6095"));
holder.view.txtCurrentQuestion2.setTextColor(Color.parseColor("#0B6095"));
holder.view.txtTitleQuestions.setTextColor(Color.parseColor("#0B6095"));
holder.view.questionsTik.visibility = View.VISIBLE
}
var absolutResultRadio = Math.abs(valueOfRadio.toInt())
// map["Q" + "_" + idIf.toString() + "_" + typeIf.toString()] = valueOfRadio
map["Q" + (position + 1).toString()] =
typeIf.toString() + "_" + absolutResultRadio * testValue
var con = maps.any { it.containsKey("Q" + (position + 1).toString()) }
if (maps.any { con == true }) {// filter
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
maps.removeIf { it.containsKey("Q" + (position + 1)) }
testnumbers = testnumbers - 1
}
testnumbers = testnumbers + 1
maps.add(map)
Log.i("maps", "in dare ejra mishe")
} else {
maps.add(map)
testnumbers = testnumbers + 1
}
}
Log.i ( "testnumber2" , testnumbers.toString())
} else {
holder.view.cardRange.visibility = View.INVISIBLE
holder.view.radioButtonFirstAAndB.text = answers[0].title
holder.view.radioButtonSecondAAndB.text = answers[1].title
holder.view.radioGroup2.setOnCheckedChangeListener { group, checkedId ->
if (checkedId == AminAmix.com.socialpersonality.R.id.radioButtonFirstAAndB) {
Log.i("Radio", "1")
valueOfRadio = "1"
}
if (checkedId == AminAmix.com.socialpersonality.R.id.radioButtonSecondAAndB) {
Log.i("Radio", "-1")
valueOfRadio = "-1"
}
val checked = group.findViewById(checkedId) as RadioButton
val list: ArrayList<String> = ArrayList()
list.add(checked.getText().toString())
Log.i("Chekkk", list.toString())
Log.i(
"checkedId", position.toString()
)
var idIf = ""
var typeIf = ""
var testValue = 0
var map = HashMap<String, String>();
var radioInt = valueOfRadio.toInt()
var selectedAnswers = questionList.questions[position].answers
if (radioInt > 0) {
typeIf = selectedAnswers[0].type
testValue = selectedAnswers[0].value
holder.view.txtCurrentQuestion.setTextColor(Color.parseColor("#0B6095"));
holder.view.txtAmountQuestion.setTextColor(Color.parseColor("#0B6095"));
holder.view.txtCurrentQuestion2.setTextColor(Color.parseColor("#0B6095"));
holder.view.txtTitleQuestions.setTextColor(Color.parseColor("#0B6095"));
holder.view.questionsTik.visibility = View.VISIBLE
} else if (radioInt < 0) {
typeIf = selectedAnswers[1].type
testValue = selectedAnswers[1].value
holder.view.txtCurrentQuestion.setTextColor(Color.parseColor("#0B6095"));
holder.view.txtAmountQuestion.setTextColor(Color.parseColor("#0B6095"));
holder.view.txtCurrentQuestion2.setTextColor(Color.parseColor("#0B6095"));
holder.view.txtTitleQuestions.setTextColor(Color.parseColor("#0B6095"));
holder.view.questionsTik.visibility = View.VISIBLE
}
var absolutResultRadio = Math.abs(valueOfRadio.toInt())
// map["Q" + "_" + idIf.toString() + "_" + typeIf.toString()] = valueOfRadio
map["Q" + (position + 1).toString()] =
typeIf.toString() + "_" + absolutResultRadio * testValue
var con = maps.any { it.containsKey("Q" + (position + 1).toString()) }
if (maps.any { con == true }) {// filter
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
maps.removeIf { it.containsKey("Q" + (position + 1)) }
}
maps.add(map)
Log.i("maps", "in dare ejra mishe")
} else {
maps.add(map)
}
}
}
Log.i("mapSize", maps.toString())
Log.i("mapSize", maps.size.toString())
if (maps.size.toInt() == questionList.questions.size
) {
Log.i("maps", "Halaaaaaaaaaaa in dare ejra mishe")
Log.i("Mapss", "SomeText: " + Gson().toJson(maps))
val dataOfTestToJson = Gson().toJson(maps).toString()
val eRegex = Regex("E_(\\d+)")
val iRegex = Regex("I_(\\d+)")
val sRegex = Regex("S_(\\d+)")
val nRegex = Regex("N_(\\d+)")
val fRegex = Regex("F_(\\d+)")
val tRegex = Regex("T_(\\d+)")
val pRegex = Regex("P_(\\d+)")
val jRegex = Regex("J_(\\d+)")
e = eRegex.findAll(dataOfTestToJson).map { it.groupValues[1].toInt() }.sum()
i = iRegex.findAll(dataOfTestToJson).map { it.groupValues[1].toInt() }.sum()
s = sRegex.findAll(dataOfTestToJson).map { it.groupValues[1].toInt() }.sum()
n = nRegex.findAll(dataOfTestToJson).map { it.groupValues[1].toInt() }.sum()
f = fRegex.findAll(dataOfTestToJson).map { it.groupValues[1].toInt() }.sum()
t = tRegex.findAll(dataOfTestToJson).map { it.groupValues[1].toInt() }.sum()
p = pRegex.findAll(dataOfTestToJson).map { it.groupValues[1].toInt() }.sum()
j = jRegex.findAll(dataOfTestToJson).map { it.groupValues[1].toInt() }.sum()
val data = JSONObject()
data.put("E", e)
data.put("I", i)
data.put("S", s)
data.put("N", n)
data.put("T", t)
data.put("F", f)
data.put("J", j)
data.put("P", p)
Log.i(
"dataSexy",
data.toString()
)
Log.i(
"mapsSexy",
"I = $i" + " " + "E = $e" + " " + "S= $s" + " " + "N = $n" + " " + "F = $f" + " " + "T = $t" + " " + "P = $p" + " " + "J = $j"
)
val context = holder.view.context
val intent = Intent(context, LoadingMbtiActivity::class.java)
intent.putExtra("e", e.toString())
intent.putExtra("i", i.toString())
intent.putExtra("s", s.toString())
intent.putExtra("n", n.toString())
intent.putExtra("f", f.toString())
intent.putExtra("t", t.toString())
intent.putExtra("p", p.toString())
intent.putExtra("j", j.toString())
intent.putExtra("data", data.toString())
context.startActivity(intent)
(context as Activity).finish()
}
holder.view.txtQuestionInRow.text = question
}
override fun getItemCount(): Int {
return questionList.questions.size
}
override fun getItemViewType(position: Int): Int {
return position
}
}
class QuestionViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
}
tps://i.stack.imgur.com/aQiS4.png
class MBTITEST : AppCompatActivity() {
lateinit var token: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_mbtitest)
window.statusBarColor = ContextCompat.getColor(this, R.color.black)
val preferences: SharedPreferences =
applicationContext.getSharedPreferences("SOCIAL_PERSONALITY", Context.MODE_PRIVATE)
token = preferences.getString("TOKEN", null).toString() //second parameter default value.
var tokenBAr = "Bearer $token"
getQuestions(tokenBAr)
}
fun getQuestions(token: String) {
val apilnterface: APIInterface = APIClient().getClient()!!.create(APIInterface::class.java)
var call: Call<QuestionList> = apilnterface.getQuestions(token)
call.enqueue(object : Callback<QuestionList> {
override fun onResponse(
call: Call<QuestionList>,
response: Response<QuestionList>
) {
if (response.code() == 200) {
// Toast.makeText(
// this#MBTITEST,
// "Testatol GolMohammadi",
// Toast.LENGTH_LONG
// )
// .show()
// Log.w("RESGetID", "${response.body().toString()}")
val dataFromResponse = response.body()
val questionList = dataFromResponse?.questions
val size = questionList?.size
val title = questionList?.get(0)?.title
print(questionList)
Log.w("QuestionListDaDa", questionList.toString())
Log.w("QuestionListDaDa", size.toString())
Log.w("QuestionListDaDa", title.toString())
runOnUiThread {
val layoutManager = LinearLayoutManager(
this#MBTITEST,
LinearLayoutManager.HORIZONTAL,
false
)
recycler_questions.layoutManager = layoutManager
recycler_questions.setHasFixedSize(true)
recycler_questions.adapter?.setHasStableIds(true)
Collections.shuffle(dataFromResponse?.questions)
recycler_questions.adapter =
dataFromResponse?.let { MbtiQuestionAdapter(it) }
txtCountTotal.text = questionList?.size.toString()
var mbtiAdapter = dataFromResponse?.let { MbtiQuestionAdapter(it) }
var testnumbers = mbtiAdapter?.testnumbers
textView15.setText(testnumbers.toString())
Log.i("testnumber", testnumbers.toString())
// btnShowRes.setOnClickListener {
// // dataFromResponse?.let { MbtiQuestionAdapter(it) }?.activateButtons(true)
// val intent = Intent(this#MBTITEST, ShowTestResultActivity::class.java)
// startActivity(intent)
// finish()
// }
}
}
if (response.code() == 400) {
try {
val jObjError = JSONObject(response.errorBody()!!.string())
Toast.makeText(
applicationContext,
jObjError.getString("message"),
Toast.LENGTH_LONG
).show()
} catch (e: Exception) {
Toast.makeText(applicationContext, e.message, Toast.LENGTH_LONG).show()
}
}
if (response.code() == 401) {
try {
val preferences: SharedPreferences =
applicationContext.getSharedPreferences(
"SOCIAL_PERSONALITY",
Context.MODE_PRIVATE
)
preferences.edit().putString("TOKEN", "").apply()
val jObjError = JSONObject(response.errorBody()!!.string())
Toast.makeText(
applicationContext,
jObjError.getString("message"),
Toast.LENGTH_LONG
).show()
} catch (e: Exception) {
Toast.makeText(applicationContext, e.message, Toast.LENGTH_LONG).show()
val intent = Intent(this#MBTITEST, FirstPageActivity::class.java)
startActivity(intent)
finish()
}
}
}
override fun onFailure(call: Call<QuestionList>, t: Throwable) {
Toast.makeText(
this#MBTITEST,
" Register is not ok",
Toast.LENGTH_LONG
)
.show()
}
})
}
}
like what #Arpit Shukla mentioned you can pass data between adapter and activity using lambdas or functions
add a function as a parameter to your adapter's constructor
class MbtiQuestionAdapter(val questionList: QuestionList,val onRadioButtonClick : (Int) -> Unit)
in your activity define a function to update your progress bar and it takes a number as a parameter or whatever you want
private fun updateProgressBar(testNumber : Int){
//update progress bar
}
pass the above function to adapter constructor when you initialize it
recycler_questions.adapter = dataFromResponse?.let { MbtiQuestionAdapter(it){number -> updateProgressBar(number)} }
lastly call the onRadioButtonClick in your adapter when you want to pass the number to your activity
onRadioButtonClick(number)
I just make a recyclerview and the data is doubled with this logic :
if(itemsList != null)
{
while (itemsList.hasNext()) {
val inFormat: DateFormat = SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS'Z'")
val outFormat: DateFormat = SimpleDateFormat("MM/dd/yyyy hh:mm")
val inFormatTwo: DateFormat = SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'")
val outFormatTwo: DateFormat = SimpleDateFormat("MM/dd/yyyy hh:mm")
val detail = itemsList.iterator().next().listIterator()
while(detail.hasNext())
{
val item = detail.next()
val status = item.status
val type = item.itemType
val pickupPoint = item.pickupPoint
val name = item.requesterDetails.elementAt(0).name
val reqDate = item.requestDate
val pickupTime = item.pickupTime
val reviewDate = item.pickupTime
val purpose = item.rejectReason
val quantity = item.quantity
val isActive = item.isActive
val isLatest = item.isLatest
var itemList : Any
val reqDateFormatted : Date?
val reqDateFix : String
reqDateFormatted = inFormat.parse(reqDate)
reqDateFix = outFormat.format(reqDateFormatted!!)
var pickupTimeFormatted : Date?
var pickupTimeFix = ""
if(pickupTime.length == 24)
{
pickupTimeFormatted = inFormat.parse(pickupTime)
pickupTimeFix = outFormat.format(pickupTimeFormatted)
} else if(pickupTime.length == 20)
{
pickupTimeFormatted = inFormatTwo.parse(pickupTime)
pickupTimeFix = outFormatTwo.format(pickupTimeFormatted!!)
}
if(isLatest == "Y")
{
itemList = DataModel(
type + " Request",
status,
name,
type,
quantity.toString(),
reqDateFix,
reviewDate,
pickupPoint,
pickupTimeFix,
purpose,
isActive,
isLatest
)
itemsData.add(itemList)
adapter.notifyDataSetChanged()
}
}
}
}
Basically, it is used to inform the user of the item they request, so the data comes from API. So, if itemsList is not null then while itemsList array has elements and inside it also exists array(s) and inside the array, I add each string to ArrayList and then isLatest string is equal to Y then add those arrays to itemList as a DataModel and then save them by adding itemList to itemsData. What makes the array doubled, thank you for your help
Notify the changes to adapter after the while loop and not after each add.
Try this:
if(itemsList != null)
{
while (itemsList.hasNext()) {
val inFormat: DateFormat = SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS'Z'")
val outFormat: DateFormat = SimpleDateFormat("MM/dd/yyyy hh:mm")
val inFormatTwo: DateFormat = SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'")
val outFormatTwo: DateFormat = SimpleDateFormat("MM/dd/yyyy hh:mm")
val detail = itemsList.iterator().next().listIterator()
while(detail.hasNext())
{
val item = detail.next()
val status = item.status
val type = item.itemType
val pickupPoint = item.pickupPoint
val name = item.requesterDetails.elementAt(0).name
val reqDate = item.requestDate
val pickupTime = item.pickupTime
val reviewDate = item.pickupTime
val purpose = item.rejectReason
val quantity = item.quantity
val isActive = item.isActive
val isLatest = item.isLatest
var itemList : Any
val reqDateFormatted : Date?
val reqDateFix : String
reqDateFormatted = inFormat.parse(reqDate)
reqDateFix = outFormat.format(reqDateFormatted!!)
var pickupTimeFormatted : Date?
var pickupTimeFix = ""
if(pickupTime.length == 24)
{
pickupTimeFormatted = inFormat.parse(pickupTime)
pickupTimeFix = outFormat.format(pickupTimeFormatted)
} else if(pickupTime.length == 20)
{
pickupTimeFormatted = inFormatTwo.parse(pickupTime)
pickupTimeFix = outFormatTwo.format(pickupTimeFormatted!!)
}
if(isLatest == "Y")
{
itemList = DataModel(
type + " Request",
status,
name,
type,
quantity.toString(),
reqDateFix,
reviewDate,
pickupPoint,
pickupTimeFix,
purpose,
isActive,
isLatest
)
itemsData.add(itemList)
}
}
}
adapter.notifyDataSetChanged()
}
Now i am writing my small molar mass calculator and i can't fix one bug. In MainActivity.kt i fill array from my .xml file, after that i use Regex to parse user input. BUT if i type, for example "C" (carbon) in my program it doesn't recognize it. WHY?
MainActivity.kt:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val adapter = MoleculeAdapter(this)
moleculeView.layoutManager = LinearLayoutManager(this)
moleculeView.setHasFixedSize(true)
moleculeView.adapter = adapter
val parser = resources.getXml(R.xml.elements)
val elements = Array(127) { Element() }
thread {
var i = 0
while (parser.eventType != END_DOCUMENT) {
if (parser.eventType == START_TAG && parser.name == "element") {
elements[i].number = parser.getAttributeIntValue(null, "number", 0)
elements[i].letter = parser.getAttributeValue(null, "letter")
elements[i].name = parser.getAttributeValue(null, "name")
val weight = parser.getAttributeValue(null, "weight")
elements[i].weight = if (weight.isNotEmpty()) weight.toFloat() else 0F
i++
}
parser.next()
}
parser.close()
}.join()
Log.i("elements:", elements.joinToString { it.toString() + "\n" })
val lowerCaseLetters = "abcdefghiklmnopqrstuy"
val elementsRegex = Regex("""[ABCDEFGHIKLMNOPRSTUVWXYZ]([$lowerCaseLetters]{2}|[$lowerCaseLetters]?)\d*""")
val digitsRegex = Regex("""\d+""")
formulaInput.doOnTextChanged { text, _, _, _ ->
lateinit var foundedElements: List<Element>
thread {
foundedElements = elementsRegex
.findAll(text ?: "")
.map {
elements.find { element ->
Log.i("value", it.value + " " + it.value)
if (it.value.filter { it.isLetter() } == element.letter) {
val number = digitsRegex.find(it.value)
if (number != null) {
try {
element.moleculeCount = number.value.toInt()
element.weight = element.weight * number.value.toInt()
} catch (e: NumberFormatException) { }
}
element.percentage = adapter.getTotalWeight(element.weight) * 100
true
} else false
}
}.filterNotNull().toList()
}.join()
adapter.insertElements(foundedElements)
}
}
}
Element.kt:
data class Element(var number: Int = -1,
var letter: String = "",
var name: String = "",
var weight: Float = 0F,
var percentage: Float = 100F,
var moleculeCount: Int = 1)
xml file item example:
<element
number="6"
letter="С"
name="Углерод"
weight="12.011" />
I can't believe it, in my xml file letter "С" was a cyrillic letter "C" (\u0421)! And because of this equals check "С" == "C" was failing.
Huge Thanks to Wiktor Stribiżew for his comment.