String request in Kotlin class - android

I m new in Kotlin and I'm trying to do a string request (with volley library and PHP)
I did this (like a Java)
val addUrl = "myurl"
val queue = Volley.newRequestQueue(this)
val postRequest = object : StringRequest(Request.Method.POST, addUrl,
Response.Listener<String> { response ->
//Toast.makeText(this, response, Toast.LENGTH_SHORT).show()
}, Response.ErrorListener {
//Toast.makeText(this, "Something wrong", Toast.LENGTH_SHORT).show()
}) {
override fun getParams(): Map<String, String> {
val params = HashMap<String, String>()
params.put("uid", uid.toString())
return params
}
}
queue.add(postRequest)
and I have error at this point
val queue = Volley.newRequestQueue(this)
Because say that I can't use "this"
Type mismatch: inferred type is DataContainer but Context! was
expected
My data container don't extend AppCompatActivity(): so I can't use a "this#Activity" as another suggestion find online
This is the companion object
class DataContainer {
val noH = 32
val TAG = "DataContainer"
private var mDb : GlucoseDataBase
private val lock = java.lang.Object()
private var lastTimeStamp : Int = 0
private val user = FirebaseAuth.getInstance().currentUser
var uid:String? = null.toString()
//private var raw_data : ByteArray = byteArrayOf()
private var readings : MutableList<ByteArray> = mutableListOf()
constructor(context : Context) {
mDb = GlucoseDataBase.getInstance(context)
}
fun append(raw_data: ByteArray, readingTime: Long, sensorId : Long) {
user?.let {
// Name, email address, and profile photo Url
//val name = user.displayName
//val email = user.email
//val photoUrl = user.photoUrl
// Check if user's email is verified
//val emailVerified = user.isEmailVerified
// The user's ID, unique to the Firebase project. Do NOT use this value to
// authenticate with your backend server, if you have one. Use
// FirebaseUser.getToken() instead.
uid = user.uid
}
synchronized(lock) {
readings.add(raw_data.copyOf())
val timestamp = RawParser.timestamp(raw_data)
if (timestamp == 0) {
mDb.sensorContactDao().insert(SensorContact(0, readingTime, sensorId, 0, 0))
return
}
// Timestamp is 2 mod 15 every time a new reading to history is done.
val minutesSinceLast = (timestamp + 12) % 15
val start = readingTime - Time.MINUTE * (15 * (noH - 1) + minutesSinceLast)
val now_history = RawParser.history(raw_data)
val now_recent = RawParser.recent(raw_data)
Log.i("UID", uid.toString());
val history_prepared = prepare(now_history, sensorId, 15 * Time.MINUTE, start, minutesSinceLast != 14 && timestamp < Time.DURATION_MINUTES, true)
val data = history_prepared.toList();
// val data2= data[0] //primo elemento più vecchio (di timestamp) //proviamo con history[0]??
//val data2 = data[0].value // elemento valore dell più vecchio
Log.i("Data History full p", data.toString());
//Log.i("Data history prepared",data2.toString());
val start_recent =
if (history_prepared.isEmpty()) {
val last = mDb.glucoseEntryDao().getLast(sensorId, true)
if (last != null) {
min(last.utcTimeStamp, readingTime - 16 * Time.MINUTE)
} else {
readingTime - 16 * Time.MINUTE
}
} else {
min(readingTime - 16 * Time.MINUTE, history_prepared.last().utcTimeStamp)
}
val recent_prepared = prepare(now_recent, sensorId, 1 * Time.MINUTE, start_recent, true, false)
val added = extend(recent_prepared) + extend(history_prepared)
mDb.sensorContactDao().insert(SensorContact(0, sensorId, readingTime, timestamp, added))
Log.i("Data recent prepared",recent_prepared.toString());
//creating volley string request
lastTimeStamp = timestamp
}
val addUrl = "myrurl"
val queue = Volley.newRequestQueue()
val postRequest = object : StringRequest(Request.Method.POST, addUrl,
Response.Listener<String> { response ->
//Toast.makeText(this, response, Toast.LENGTH_SHORT).show()
}, Response.ErrorListener {
//Toast.makeText(this, "Something wrong", Toast.LENGTH_SHORT).show()
}) {
override fun getParams(): Map<String, String> {
val params = HashMap<String, String>()
params.put("uid", uid.toString())
return params
}
}
queue.add(postRequest)
}
fun get_sz_raw_data() : Int {
return readings.size
}
fun get_raw_data(i: Int) : ByteArray{
synchronized(lock){
if(0<= i && i < readings.size)
return readings[i]
else
return byteArrayOf()
}
}
fun insert(v: List<GlucoseEntry>) {
synchronized(lock){
if(size() != 0) return
for(g in v) {
mDb.glucoseEntryDao().insert(g)
}
}
Log.d(TAG, String.format("inserted %d vales into database", v.size))
}
private fun extend(v: List<GlucoseReading>) : Int {
synchronized(lock) {
val toExtend = v.filter { g: GlucoseReading -> g.status != 0 && g.value > 10 }
.map { g: GlucoseReading -> GlucoseEntry(g, 0) }
for (r: GlucoseEntry in toExtend) {
mDb.glucoseEntryDao().insert(r)
}
Log.d(TAG, "Inserted into db!")
return toExtend.size
}
}
// Inspects last entry from the same sensor and filters out all that are already logged.
private fun prepare(chunks : List<SensorChunk>,
sensorId : Long,
dt : Long,
start : Long,
certain : Boolean,
isHistory: Boolean) : List<GlucoseReading> {
val lastRecent = mDb.glucoseEntryDao().getLast(sensorId, isHistory)
if(lastRecent != null) {
var match = -1
for (i in 0 until chunks.size) {
if (lastRecent.eq(chunks[i])) {
match = i
}
}
if(match > -1) {
val range = IntRange(match + 1, chunks.size - 1)
if(!certain)
return chunks.slice(range)
.mapIndexed { i: Int, chunk: SensorChunk ->
GlucoseReading(chunk,
lastRecent.utcTimeStamp + (i + 1) * dt, sensorId)
}
else {
return chunks.mapIndexed { i: Int, chunk: SensorChunk ->
GlucoseReading(chunk,
start + i * dt, sensorId)
}.slice(range)
}
}
}
return chunks.mapIndexed { i: Int, chunk: SensorChunk ->
GlucoseReading(chunk, start + i * dt, sensorId)
}
}
fun nice(g : GlucoseEntry) : Boolean = g.status == 200 && (g.value < 5000 && g.value > 10)
fun get(after: Long, before : Long) : List<GlucoseEntry> {
return get(after, before, true)
}
fun get(after: Long, before : Long, nice : Boolean) : List<GlucoseEntry> {
synchronized(lock) {
val v = mDb.glucoseEntryDao().getBetween(after, before).orEmpty().sortedBy{ g -> g.utcTimeStamp }
if(!nice) return v
else return v.filter{g -> nice(g)}
}
}
private fun last() : GlucoseEntry? {
return mDb.glucoseEntryDao().getLast(false)
}
fun guess() : Pair<GlucoseReading, GlucoseReading>? {
synchronized(lock){
val last = last()
if(last == null || !nice(last)) return null
val last_as_reading = GlucoseReading(last.value, last.utcTimeStamp, last.sensorId, last.status, false, 0)
val candidates = get(last.utcTimeStamp - Time.MINUTE*5, last.utcTimeStamp)
val real = candidates.filter{g -> g.history == false && g.sensorId == last.sensorId}
if(real.isEmpty()) return null
val entry = real.first()
val guess = last.value * 2 - entry.value
val time = last.utcTimeStamp * 2 - entry.utcTimeStamp
return Pair(last_as_reading, GlucoseReading(guess,
time,
last.sensorId, last.status, false, 0))
}
}
fun lastTimeStamp() : Int {
synchronized(lock){return lastTimeStamp}
}
fun size() : Int {
synchronized(lock) {
val sz = mDb.glucoseEntryDao().getSize()
return sz
}
}
fun insertManual(manual : ManualGlucoseEntry) {
synchronized(lock) {
mDb.manualEntryDao().insert(manual)
}
}
companion object {
private var INSTANCE : DataContainer? = null
fun getInstance(context : Context) : DataContainer {
if (INSTANCE == null) {
synchronized(DataContainer::class) {
if(INSTANCE == null)
INSTANCE = DataContainer(context)
}
}
return this.INSTANCE!!
}
/* fun applicationContext() : Context {
return INSTANCE!!.applicationContext
}*/
fun destroyInstance(){
synchronized(DataContainer::class){
GlucoseDataBase.destroyInstance()
if(INSTANCE != null){
INSTANCE = null
}
}
}
}
}
Any suggestion?

Try to change your DataContainer implementation like below and use context
class DataContainer(val context : Context) {
....
init {
mDb = GlucoseDataBase.getInstance(context)
}
....
val queue = Volley.newRequestQueue(context)
}

Related

Installing an APK Programmatically (Android 12)

I'm attempting to install an APK programmatically on Android 12 but seem to be running into unknown issues at this point. All advice I've found regarding installing an APK programmatically seem to be deprecated.
Currently, I'm able to save my file but whenever I attempt to install it using PackageManager.PackageInstaller, it fails silently and I'm unable to find anything in the logs suggesting what the failure might've been.
Here's my package installer object.
object PackageInstaller {
#SuppressLint("WrongConstant")
#Throws(IOException::class)
fun installPackage(
context: Context,
installSessionId: String?,
packageName: String?,
apkStream: InputStream?
) {
val packageManger = context.packageManager
val packageInstaller = packageManger.packageInstaller
val params = android.content.pm.PackageInstaller.SessionParams(
android.content.pm.PackageInstaller.SessionParams.MODE_FULL_INSTALL
)
params.setAppPackageName(packageName)
var session: android.content.pm.PackageInstaller.Session? = null
try {
val sessionId = packageInstaller.createSession(params)
session = packageInstaller.openSession(sessionId)
val out = session.openWrite(installSessionId!!, 0, -1)
val buffer = ByteArray(1024)
var length: Int
var count = 0
if (apkStream != null) {
while (apkStream.read(buffer).also { length = it } != -1) {
out.write(buffer, 0, length)
count += length
}
}
session.fsync(out)
out.close()
val intent = Intent
intent.addFlags(Intent.ACTION_PACKAGE_ADDED)
Log.v("installer", "Installing..?")
session.commit(
PendingIntent.getBroadcast(
context, sessionId,
intent, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
} else {
PendingIntent.FLAG_UPDATE_CURRENT
}
).intentSender
)
}finally {
session?.close()
}
}
}
At this point I'm pretty lost as to where to look next. Does anyone even know if this is still possible? Or a solution to this issue?
You can try with this it is working with android 12
class DownloadApk(private var context: WeakReference<Context>) {
#JvmOverloads
fun startDownloadingApk(url: String, fileName: String = "App Update") {
if (URLUtil.isValidUrl(url)) {
DownloadNewVersion(context, url, fileName).execute()
}
}
#Suppress("DEPRECATION")
private class DownloadNewVersion(
private val context: WeakReference<Context>,
val downloadUrl: String,
val fileName: String
) : AsyncTask<String, Int, Boolean>() {
private lateinit var bar: ProgressDialog
override fun onPreExecute() {
super.onPreExecute()
bar = ProgressDialog(context.get()).apply {
setCancelable(false)
setMessage("Downloading...")
isIndeterminate = true
setCanceledOnTouchOutside(false)
show()
}
}
override fun onProgressUpdate(vararg values: Int?) {
super.onProgressUpdate(*values)
var msg = ""
val progress = values[0]
if (progress != null) {
bar.progress = progress
msg = if (progress > 99) "Finishing... " else "Downloading... $progress%"
}
bar.apply {
isIndeterminate = false
max = 100
setMessage(msg)
}
}
override fun onPostExecute(result: Boolean?) {
super.onPostExecute(result)
bar.dismiss()
if (result != null && result) {
context.get()?.let {
Toast.makeText(it, "Update Done", Toast.LENGTH_SHORT).show()
}
} else {
context.get()?.let {
Toast.makeText(it, "Error: Try Again", Toast.LENGTH_SHORT).show()
}
}
}
override fun doInBackground(vararg p0: String?): Boolean {
var flag = false
try {
val path =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
.toString() + "/"
var outputFile = File("$path$fileName.apk")
var repetition = 1
while (outputFile.exists()) {
outputFile = File("$path$fileName ($repetition).apk")
repetition++
}
val directory = File(path)
if (!directory.exists()) {
directory.mkdirs()
}
val url = URL(downloadUrl)
val c = url.openConnection() as HttpURLConnection
c.requestMethod = "GET"
c.connect()
val fos = FileOutputStream(outputFile)
val inputStream = c.inputStream
val totalSize = c.contentLength.toFloat() //size of apk
val buffer = ByteArray(1024)
var len1: Int
var per: Float
var downloaded = 0f
while (inputStream.read(buffer).also { len1 = it } != -1) {
fos.write(buffer, 0, len1)
downloaded += len1
per = (downloaded * 100 / totalSize)
publishProgress(per.toInt())
}
fos.close()
inputStream.close()
openNewVersion(outputFile.path)
flag = true
} catch (e: MalformedURLException) {
Log.e("DownloadApk", "Update Error: " + e.message)
flag = false
} catch (e: IOException) {
e.printStackTrace()
}
return flag
}
private fun openNewVersion(location: String) {
val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(
getUriFromFile(location),
"application/vnd.android.package-archive"
)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
context.get()?.startActivity(intent)
}
private fun getUriFromFile(filePath: String): Uri? {
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
Uri.fromFile(File(filePath))
} else {
context.get()?.let {
FileProvider.getUriForFile(
it,
it.packageName + ".provider",
File(filePath)
)
}
}
}
}
}

issue with firebase and kotlin

For a long time I can not solve two problems, for some reason the elements in my RecyclerView are not displayed immediately but after interacting with something, for example when you click on the message field, the second problem is that when you send an image, it is once written to the database, but 3 times is displayed on screen, but if you go to the chat it is displayed once, with text messages no such problem
private fun listenMessage() {
database
.collection(KEY_COLLECTION_USERS)
.document(preferenceManager.getString(KEY_USER_ID)!!)
.collection(KEY_COLLECTION_CHAT)
.addSnapshotListener { value, error ->
if (error != null) {
return#addSnapshotListener
} else {
if (value == null) {
return#addSnapshotListener
} else {
for (documentChange in value.documentChanges) {
if (documentChange.type == DocumentChange.Type.ADDED) {
var doc = documentChange.document
if (doc.getString(KEY_MESSAGE_RECEIVER_ID) == receiverUser.uid) {
var text = doc.getString(KEY_MESSAGE).toString()
var id = doc.getString(KEY_MESSAGE_ID).toString()
var receiverId = doc.getString(KEY_MESSAGE_RECEIVER_ID).toString()
var date = doc.getDate(KEY_MESSAGE_DATE)!!
var isChecked = doc.getBoolean(KEY_MESSAGE_ISCHECKED)!!
var type = doc.getString(KEY_TYPE_MESSAGE).toString()
var message = Message(text, id, receiverId, date, isChecked, type)
messages.add(message)
}
}
}
val chatComparator =
Comparator { obj1: Message, obj2: Message -> obj1.date.compareTo(obj2.date) }
Collections.sort(messages, chatComparator)
var messages_test = ArrayList(messages)
userChatAdpater.updateList(messages_test)
if (messages.size != 0) {
mBinding.rvUserChat.smoothScrollToPosition(messages.size - 1)
}
}
}
}
database
.collection(KEY_COLLECTION_USERS)
.document(receiverUser.uid)
.collection(KEY_COLLECTION_CHAT)
.addSnapshotListener { value, error ->
if (error != null) {
return#addSnapshotListener
} else {
if (value == null) {
return#addSnapshotListener
} else {
for (documentChange in value.documentChanges) {
if (documentChange.type == DocumentChange.Type.ADDED) {
var doc = documentChange.document
if (doc.getString(KEY_MESSAGE_RECEIVER_ID) == preferenceManager.getString(
KEY_USER_ID
)
) {
var text = doc.getString(KEY_MESSAGE).toString()
var id = doc.getString(KEY_MESSAGE_ID).toString()
var receiverId = doc.getString(KEY_MESSAGE_RECEIVER_ID).toString()
var date = doc.getDate(KEY_MESSAGE_DATE)!!
var isChecked = doc.getBoolean(KEY_MESSAGE_ISCHECKED)!!
var type = doc.getString(KEY_TYPE_MESSAGE).toString()
var message = Message(text, id, receiverId, date, isChecked, type)
messages.add(message)
}
}
}
val chatComparator =
Comparator { obj1: Message, obj2: Message -> obj1.date.compareTo(obj2.date) }
Collections.sort(messages, chatComparator)
var messages_test = ArrayList(messages)
userChatAdpater.updateList(messages_test)
if (messages.size != 0) {
mBinding.rvUserChat.smoothScrollToPosition(messages.size - 1)
}
}
}
}
}
is a message listener
class UserChatAdapter( messages:List<Message>,receiverImage: String,senderId:String) :
RecyclerView.Adapter<UserChatAdapter.UserChatViewHolder>() {
var messages = messages
var receiverImage = receiverImage
var senderID = senderId
open class UserChatViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private fun getBitmapFromEncodedString(encodedImage:String): Bitmap {
val bytes = Base64.decode(encodedImage, Base64.DEFAULT)
return BitmapFactory.decodeByteArray(bytes,0,bytes.size)
}
private fun getReadableDateTime(date: Date): String {
return SimpleDateFormat("MMMM dd, yyyy - hh:mm a", Locale.getDefault()).format(date)
}
fun bind(type:Int, view:View, position: Int, messages: List<Message>, receiverImage: String){
if(type == SENT_TEXT){
SentTextMessageViewHolder(view).message.text = messages.get(position).message
SentTextMessageViewHolder(view).dateTime.text = getReadableDateTime(messages.get(position).date)
}else if( type == SENT_IMAGE){
SentImageMessageViewHolder(view).message.setImageURI(Uri.parse(messages.get(position).message))
SentImageMessageViewHolder(view).dateTime.text = getReadableDateTime(messages.get(position).date)
}else if(type == RECEIVED_TEXT){
ReceivedTextMessageViewHolder(view).message.text = messages.get(position).message
ReceivedTextMessageViewHolder(view).dateTime.text = getReadableDateTime(messages.get(position).date)
ReceivedTextMessageViewHolder(view).imageReceiver.setImageBitmap(getBitmapFromEncodedString(receiverImage))
}else if(type == RECEIVED_IMAGE){
ReceivedImageMessageViewHolder(view).message.setImageURI(Uri.parse(messages.get(position).message))
ReceivedImageMessageViewHolder(view).dateTime.text = getReadableDateTime(messages.get(position).date)
ReceivedImageMessageViewHolder(view).imageReceiver.setImageBitmap(getBitmapFromEncodedString(receiverImage))
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserChatViewHolder {
lateinit var viewHolder:UserChatViewHolder
if (viewType == SENT_TEXT) {
val layout = R.layout.item_container_sent_message
val view = LayoutInflater.from(parent.context).inflate(layout, parent, false)
viewHolder = SentTextMessageViewHolder(view)
} else if(viewType == RECEIVED_TEXT) {
val layout = R.layout.item_container_received_message
val view = LayoutInflater.from(parent.context).inflate(layout, parent, false)
viewHolder = ReceivedTextMessageViewHolder(view)
}else if(viewType == RECEIVED_IMAGE){
val layout = R.layout.item_container_received_message_image
val view = LayoutInflater.from(parent.context).inflate(layout, parent, false)
viewHolder = ReceivedImageMessageViewHolder(view)
}else if(viewType == SENT_IMAGE){
val layout = R.layout.item_container_sent_message_image
val view = LayoutInflater.from(parent.context).inflate(layout, parent, false)
viewHolder = SentImageMessageViewHolder(view)
}
return viewHolder
}
override fun onBindViewHolder(holder: UserChatViewHolder, position: Int) {
holder.bind(holder.itemViewType,holder.itemView,position,messages,receiverImage)
}
override fun getItemCount(): Int {
return messages.size
}
fun updateList(newMessages: ArrayList<Message>){
val oldList = messages
val newList = newMessages
val diffResult: DiffUtil.DiffResult = DiffUtil.calculateDiff(
UserChatDiffCallBack(oldList,newList)
)
messages = newMessages
diffResult.dispatchUpdatesTo(this)
}
override fun getItemViewType(position: Int): Int {
if(messages.get(position).type == MESSAGE_TYPE_IMAGE){
if (senderID == messages.get(position).receiverID) {
return RECEIVED_IMAGE
} else {
return SENT_IMAGE
}
}else{
if (senderID == messages.get(position).receiverID) {
return RECEIVED_TEXT
} else {
return SENT_TEXT
}
}
}
}
is an adapter for RecyclerView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mGetContent = registerForActivityResult(ActivityResultContracts.GetContent(),
ActivityResultCallback {
val intent = Intent(APP_ACTIVITY, CropperAcrtivity::class.java)
intent.putExtra("DATA", it.toString())
startActivityForResult(intent, 101)
})
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == -1 && requestCode == 101) {
var result = data!!.getStringExtra("RESULT")
var resultUri: Uri = Uri.parse(result)
if (resultUri != null) {
sendMessageAsImage(resultUri)
}
}
}
private fun sendMessageAsImage(image: Uri) {
var text = image.toString()
var id = UUID.randomUUID().mostSignificantBits.toString()
val message = Message(text, id, receiverUser.uid, Date(), false, MESSAGE_TYPE_IMAGE)
database.collection(KEY_COLLECTION_USERS)
.whereEqualTo(KEY_UID,preferenceManager.getString(KEY_UID))
.get().addOnCompleteListener {
it.getResult().documents.get(0).reference.collection(KEY_COLLECTION_CHAT).add(message)
}
}

Android Kotlin load only one more element to recyclerview problem

I want to load just one element with one scroll gesture. Now it is like one scroll gesture loads 1 or few new elements (depends on time of scroll gesture). As a solution I could do this gesture in shorter time than 500ms or make this postDelayed's delay longer but I guess there are better solutions for that. Do you have any ideas how to do that?
This app is written in MVP pattern. Here is my code:
CurrencyFragmentList.kt
private fun addScrollerListener() {
rvItem.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(_rvItem: RecyclerView, newState: Int) {
super.onScrollStateChanged(_rvItem, newState)
Log.e("scroll", isLoading.toString())
if (!isLoading) {
if (!_rvItem.canScrollVertically(1)) {
loadMore()
isLoading = true
}
}
}
})
}
private fun loadMore() {
showProgressDialog()
var numberOfDays = mainPresenter.getNumberOfMinusDays()
numberOfDays++
mainPresenter.saveNumberOfMinusDaysIntoSp(numberOfDays)
var dateMinusXDays = mainPresenter.currentDateMinusXDaysToStr(numberOfDays)
val nextLimit = listSize + 1
for (i in listSize until nextLimit) {
if (mainPresenter.checkIfSuchDateExistsinSp(dateMinusXDays)) {
Log.d("such date already exists in shared prefs", dateMinusXDays)
handler.postDelayed({
mainPresenter.processDateWithoutMakingACall(dateMinusXDays)
}, 500)
} else {
mainPresenter.makeACall(dateMinusXDays)
Log.d("retrofit call made", dateMinusXDays)
}
}
itemAdapter.notifyDataSetChanged()
}
override fun hideProgressDialog() {
if (apiResponseList.size > 1) {
apiResponseList.removeAt(apiResponseList.size - 1)
listSize = apiResponseList.size
itemAdapter.notifyItemRemoved(listSize)
} else progress_bar.visibility = View.GONE
isLoading = false
}
override fun assignResponseToRecyclerview(apiResponse: ApiResponse?) {
rvItem.apply {
layoutManager = _layoutManager
apiResponseList.add(apiResponse!!)
itemAdapter = activity?.let { ItemAdapter(apiResponseList, it) }!!
adapter = itemAdapter
}
Log.e("assign", isLoading.toString())
}
MainPresenter.kt
override fun makeACall(date: String?) {
//view.showProgressDialog()
date?.let { restModel.fetchApiResponse(this, it) }
}
fun processDateWithoutMakingACall(date: String) {
val apiResponse = processRawJson(sp.getString(date, "").toString())
passResponseToView(apiResponse)
}
override fun processRawJson(rawJson: String): ApiResponse {
val parser = JsonParser()
val rootObj = parser.parse(rawJson).asJsonObject
var ratesObj = JsonObject()
var ratesKeys: Set<String> = HashSet()
val ratesArrayList: ArrayList<Currency> = ArrayList()
val rootKeys = rootObj.keySet();
var baseValue = ""
var dateValue = ""
for (key in rootKeys) {
if (key == "base")
baseValue = rootObj.get(key).asString
if (key == "date")
dateValue = rootObj.get(key).asString
if (key == "rates") {
ratesObj = rootObj.get(key).asJsonObject
ratesKeys = ratesObj.keySet()
}
}
for (key2 in ratesKeys) {
Log.e("ratesKey", key2)
Log.e("ratesValue", ratesObj.get(key2).asFloat.toString())
ratesArrayList.add(Currency(key2, ratesObj.get(key2).asFloat))
}
saveRawJsonIntoSp(rawJson, dateValue)
return ApiResponse(baseValue, dateValue, ratesArrayList, false)
}
override fun passResponseToView(apiResponse: ApiResponse?) {
view.hideProgressDialog()
view.assignResponseToRecyclerview(apiResponse)
}
RestModel.kt
override fun fetchApiResponse(presenter: MainPresenter, date: String) {
job = CoroutineScope(Dispatchers.IO).launch {
val response = userService.getCurrenciesForDate(date)
withContext(Dispatchers.Main) {
if (response.isSuccessful) {
val rawJson = response.body()
val apiResponse = presenter.processRawJson(rawJson)
presenter.passResponseToView(apiResponse)
}
}
}
}
Any help will be really appreciated. Thank you in advance!
Try out the SnapHelper, it might slow layout manager to make more callbacks and stop overloading

WorkManager beginUniqueWork queue not getting called after first work

I'm using WorkManager 1.0.0-alpha02
I've created my worker class like:
class PrintWorker: Worker(){
override fun doWork(): WorkerResult {
try {
val label: String = inputData.getString(LABEL_ARG_CONTENIDO, null)
val isLastLabel: Boolean = inputData.getBoolean(LABEL_ARG_IS_LAST,false)
var result = Printer(applicationContext).print(label)
var outPut: Data = Data.Builder().putString("PrinterResponse",result.printerResponse).putBoolean(LABEL_ARG_IS_LAST,isLastLabel).build()
outputData = outPut
return result.workResult
}catch (e: Exception){
return WorkerResult.FAILURE
}
}
companion object {
const val LABEL_ARG_CONTENIDO = "Label"
const val LABEL_ARG_IS_LAST = "Position"
}
}
and then in my viewmodel I've schedulled the work chain like:
var myQueue: WorkContinuation? = null
for (label in labelEntities){
val newPrintWork = OneTimeWorkRequest.Builder(PrintWorker::class.java)
val builder = Data.Builder()
var data: Data
builder.putString(PrintWorker.LABEL_ARG_CONTENIDO, label.contenido)
if(myQueue == null){
data = builder.build()
newPrintWork.setInputData(data)
myQueue = WorkManager.getInstance().beginUniqueWork(printWorkId,ExistingWorkPolicy.REPLACE,newPrintWork.build())
}
else{
if(labelEntities.indexOf(label) == labelEntities.size - 1)
builder.putBoolean(PrintWorker.LABEL_ARG_IS_LAST, true)
data = builder.build()
newPrintWork.setInputData(data)
myQueue.then(newPrintWork.build())
}
}
myQueue?.enqueue()
finally in another piece of code I'm observing it with:
viewmodel.printStatus.observe(this, Observer { works ->
if(works!= null){
if(works.filter { it.state == State.FAILED}.isNotEmpty()){
MyWorkManager().cancelPrinting()
context?.let { showDialog(MyAlertDialogManager(it).noMacAddressErrorDialog()) }
}
if(works.filter { it.state == State.SUCCEEDED }.size == works.size &&
works.isNotEmpty() &&
works.filter { it.outputData.getBoolean(LABEL_ARG_IS_LAST,false) }.isNotEmpty()){
context?.let { showDialog(MyAlertDialogManager(it).confirmPrintedCorrectly(factura,this)) }
}
}
})
The first work gets done right after enqueueing and returns Worker.WorkerResult.SUCCESS but the rest of the chain doesnt gets called

RecyclerView not updating View

I have a recycler view. For the first time, it loads all the data and the view is shown perfect. But when the data is added dynamically, pull to refresh, I add it to the list of data and call notifyDataSetChanged. It increases the count of the list and the list is updated with the latest data but the view is not updating with the latest data added to the list. onBindViewHolder has the updated listView size and the listView has all the valid data within it.
override fun onBindViewHolder(holder: HistoryListAdapter.ViewHolder?, position: Int) {
info("onBindViewHolder =>"+listAssets.size)
info("onBindViewHolder itemCount =>"+itemCount)
info("onBindViewHolder position =>"+position)
val notesButton = holder?.notesButton
val notesView = holder?.notesTextView
val dateTime = listAssets[position].date
val location = listAssets[position].location
val sessionId = listAssets[position].id
holder?.sessionID = sessionId
holder?.portraitImageView?.setImageDrawable(listAssets[position].image)
holder?.titleTextView?.text = DateTimeFormatter.getFormattedDate(context, dateTime)
val timeString = DateTimeFormatter.getFormattedTime(context, dateTime)
if (location.length != 0) {
holder?.subtitleTextView?.text = "$timeString # $location"
} else {
holder?.subtitleTextView?.text = "$timeString"
}
val data = listAssets[position].data
for (actionData in data) {
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val parent = inflater.inflate(R.layout.history_card_action, null)
val icon = parent?.findViewById(R.id.historyActionIcon) as ImageView
val title = parent?.findViewById(R.id.historyActionTitle) as TextView
val subtitle = parent?.findViewById(R.id.historyActionSubtitle) as TextView
var iconDrawable: Drawable? = null
when(actionData.type) {
ActionType.HEART -> {
iconDrawable = ContextCompat.getDrawable(context, R.drawable.heart)
}
ActionType.LUNGS -> {
iconDrawable = ContextCompat.getDrawable(context, R.drawable.lungs)
}
ActionType.TEMPERATURE -> {
iconDrawable = ContextCompat.getDrawable(context, R.drawable.temperature)
}
}
icon.setImageDrawable(iconDrawable)
val titleString = actionData.title
titleString?.let {
title.text = titleString
}
val subtitleString = actionData.subtitle
subtitleString?.let {
subtitle.text = subtitleString
}
holder?.actionContainer?.addView(parent)
}
val notes = listAssets[position].notes
notesView?.text = notes
if (notes.length == 0) {
notesButton?.layoutParams?.width = 0
} else {
notesButton?.layoutParams?.width = toggleButtonWidth
}
if (expandedNotes.contains(sessionId)) {
notesView?.expandWithoutAnimation()
} else {
notesView?.collapseWithoutAnimation()
}
notesButton?.onClick {
notesView?.toggleExpansion()
}
}
data class ListAssets(val id: String,
val date: Date,
val location: String,
val notes: String,
val image: Drawable,
val data: ArrayList<ListData>)
data class ListData(val type: ActionType,
val title: String?,
val subtitle: String?)
override fun onViewRecycled(holder: HistoryListAdapter.ViewHolder?) {
super.onViewRecycled(holder)
if (holder != null) {
holder.actionContainer.removeAllViews()
val notesTextView = holder.notesTextView
if (notesTextView != null) {
if (notesTextView.expandedState) {
val sessionID = holder.sessionID
sessionID?.let {
val sessionSearch = expandedNotes.firstOrNull {
it.contentEquals(sessionID)
}
if (sessionSearch == null) {
expandedNotes.add(sessionID)
}
}
} else {
val sessionID = holder.sessionID
sessionID?.let {
val sessionSearch = expandedNotes.firstOrNull {
it.contentEquals(sessionID)
}
if (sessionSearch != null) {
expandedNotes.remove(sessionSearch)
}
}
}
}
}
}
ActionView is Enum.
Kindly please let me know if I am doing anything wrong.

Categories

Resources