Sep 10 | 7:25 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Abhishek K. | has entered the room |
Mark M. |
hello, Abhishek!
|
Mark M. |
how can I help you today?
|
Abhishek K. |
Hello
|
Abhishek K. |
Hey Mark, actually I'm stuck with my implementation of ListenableWorker
|
Mark M. |
OK, I have not used that directly, only via Worker, but perhaps I can still help
|
Sep 10 | 7:30 PM |
Abhishek K. |
I've to use a library to download a file over the internet and this thing I have to do even if app is in background, hence I started using WOrkManager. Now, I started with CorotuineWorker, but as the library has its own thread of execution, I got into a situation where CoRoutineWorker completes its execution before the library completes in completion callback
|
Abhishek K. |
First question is - is there any way we can block the CorotuineWOrker's thread and complete it only in completion callback of the library?
|
Mark M. |
are you using suspendCoroutine() or suspendCancellableCoroutine()? or how are you setting up bridging between the callback API and coroutines?
|
Sep 10 | 7:35 PM |
Abhishek K. |
no, I was not aware of of either of it at the time of implementation. And hence I read about ListenableWorker, where google says that if we want to have our own thread execution, we can go for it. Now when I used ListenableWorker, setProgressAsync is not updating the Livedata in my activity
|
Mark M. |
*Elements of Kotlin Coroutines* has material on suspendCoroutine() and suspendCancellableCoroutine(): https://wares.commonsware.com/app/internal/book...
|
Abhishek K. |
So you're saying, using one of these 2, we can suspend the CoroutineWorker's execution and completes it in one of our callback from the library?
|
Mark M. |
correct
|
Abhishek K. |
that sounds great.
|
Abhishek K. |
Mark, one more thing
|
Abhishek K. |
in any case if I have to use ListenableWorker in my situation, why would setProgressAsync not update the LiveData?
|
Mark M. |
I have no idea, sorry
|
Abhishek K. |
didn't find much over the internet about ListenableWorker
|
Sep 10 | 7:40 PM |
Mark M. |
I assume that the LiveData that you are referring to is a workinfo one?
|
Abhishek K. |
Yeah
|
Mark M. |
such as from getWorkInfoByIdLiveData()?
|
Abhishek K. |
yeah, exactly that one
|
Tad F. | has entered the room |
Mark M. |
OK, then, yeah, I don't know why that is not working for you
|
Tad F. |
Hi Mark!
|
Mark M. |
you might try peeking at the source code to Worker or RxWorker to see if you see anything there that might give you some clues
|
Mark M. |
(hi, Tad! I'll be with you shortly!)
|
Mark M. |
or, try the coroutine options that we discussed
|
Abhishek K. |
Okay mark.
|
Mark M. |
if you're already into coroutines, that would be the direction that I would go
|
Mark M. |
let me take a question from Tad, and I will come back to you in a bit
|
Abhishek K. |
CoroutineWorker sounds better
|
Mark M. |
Tad: your turn! how can I help you today?
|
Tad F. |
I am struggling a little bit trying to properly do type definition with Generics
|
Tad F. |
I have an Abstract "Chooser" class, which defines a RecyclerView adapter and holder, in a generic way like this;
|
Tad F. |
abstract class ChooserAdapter<T extends CardListable, VH extends ChooserHolder<T>> extends RecyclerView.Adapter<VH> {
|
Tad F. |
View paste
|
Tad F. |
This class also needs access to a member variable which it expects subclasses will provide to it.
|
Sep 10 | 7:45 PM |
Tad F. |
The variable is: ChooserAdapter<CardListable,ChooserHolder<CardListable>> mChooserAdapter;
|
Tad F. |
The method this class calls its subclasses to get the proper implementation is:
|
Tad F. |
protected abstract ChooserAdapter<CardListable,ChooserHolder<CardListable>> getAdapterForRecyclerView();
|
Tad F. |
This is all well and good, and all this compiles cleanly.
|
Tad F. |
On my implementation class, I also have this working
|
Tad F. |
A class that choose "Contact" objects for example:
|
Tad F. |
class ContactChooserAdapter extends ChooserAdapter<Contact, ContactChooserViewHolder> {
|
Tad F. |
class ContactChooserViewHolder extends ChooserHolder<Contact>
|
Tad F. |
The PROBLEM is trying to implement the abstract method that the parent class expects
|
Tad F. |
It seems that this non-typed example:
|
Tad F. |
View paste
|
Tad F. |
Works fine, but of course Lint complains
|
Tad F. |
"Raw use of paramaterized class", which it should
|
Tad F. |
But I can't seem to get the typed parameters correct
|
Mark M. |
how is Chooser itself declared? it feels like you need generics there and in the abstract function definition
|
Mark M. |
protected abstract ChooserAdapter<T,ChooserHolder<T>> getAdapterForRecyclerView();
|
Mark M. |
or: protected abstract ChooserAdapter<T,VH> getAdapterForRecyclerView();
|
Sep 10 | 7:50 PM |
Tad F. |
I can do that, and it compiles, but one of the behaviors I need from the implementing classes is that I know that "T" has implemented this interface called "CardListable", because I used methods on it in the abstract class.
|
Tad F. |
I tried:
|
Tad F. |
View paste
|
Tad F. |
But that fails compilation
|
Tad F. |
For example - I have this line in the abstract class:
|
Tad F. |
mSelectedPositions.putBoolean(mChooserAdapter.getData().get(0).getId(), true);
|
Tad F. |
that "getId()" method is in CardListable interface
|
Tad F. |
So if I do: protected abstract ChooserAdapter<T,ChooserHolder<T>> getAdapterForRecyclerView();
|
Tad F. |
I don't get that, and I have to cast that call to CardListable
|
Tad F. |
Which kind of foils the whole point of what I'm trying to do with the generics
|
Mark M. |
declare it as T extends CardListable in your Chooser declaration
|
Tad F. |
I think I tried that actually
|
Tad F. |
But I'll check
|
Mark M. |
I would expect your declaration of Chooser to look a lot like the ChooserAdapter one you pasted in earlier
|
Mark M. |
insofar as it uses T extends CardListable
|
Tad F. |
Are you talking about the declaration of the method that returns the adapter?
|
Mark M. |
then your getAdapterForRecyclerView() abstract declaration can return stuff based on T
|
Tad F. |
When you say "Chooser", what are you referring to?
|
Mark M. |
In my "I would expect" sentence, I was referring to the class
|
Tad F. |
OK so you mean my implementation of the abstract ChooserAdapter?
|
Tad F. |
ContactChooserAdapter?
|
Tad F. |
Sorry, I'm confused
|
Mark M. |
I am going back to: "I have an Abstract "Chooser" class, which defines a RecyclerView adapter and holder, in a generic way like this"
|
Sep 10 | 7:55 PM |
Mark M. |
that class, called Chooser, needs generics in its declaration
|
Mark M. |
(at least, I think -- it's tough to keep all this straight)
|
Tad F. |
OK sorry - let me be more precise. I have an AbstractChooserActivity. Inside that I have a ChooserAdapter and a ChooserHolder.
|
Tad F. |
Both of the latter are abstract
|
Tad F. |
that's what I posted above
|
Mark M. |
so is AbstractChooserActivity, if the name is accurate
|
Tad F. |
Yes - I have a series of activities in my app, all of which "choose something", so I've tried to abstract out common behavior to this base class
|
Tad F. |
All of them have a recyclerview.
|
Mark M. |
I think AbstractChooserActivity's declaration needs its own generics for T and VH
|
Mark M. |
that is basically the "root" of your tree of related classes that are using generics
|
Mark M. |
(activity using the adapter that uses the viewholder)
|
Tad F. |
Hmmmm.... ok. I have not implemented any constructors in any activities. Just overloaded onCreate(), etc.
|
Tad F. |
This class extends AppCompatActivity
|
Mark M. |
you don't need a constructor
|
Tad F. |
Where do the generics go?
|
Mark M. |
abstract class AbstractChooserActivity<T extends CardListable, VH extends ChooserHolder<T>>
|
Mark M. |
protected abstract ChooserAdapter<T, VH> getAdapterForRecyclerView();
|
Tad F. |
Oh ok - you mean at the scope of the entire class, etc.
|
Tad F. |
ok
|
Mark M. |
right
|
Tad F. |
ok I'll play with that.
|
Sep 10 | 8:00 PM |
Mark M. |
let me take another question from Abhishek, and I'll come back to you in a bit
|
Abhishek K. |
Hey Mark, can I come in?
|
Tad F. |
Sure - that's it for me anyway, thanks!
|
Mark M. |
yes! do you have another question?
|
Abhishek K. |
I just tried suspendCoroutine while you guys were having the discussion, it seems like suspendCoroutine is already deprecated
|
Abhishek K. |
and one more thing, when I use resumeWithException or resume, it says, "Method are absent in corotuine class since 1.3"
|
Mark M. |
suspendCancellableCoroutine() isn't according to the docs: https://kotlin.github.io/kotlinx.coroutines/kot...
|
Mark M. |
but, yeah, something is up with suspendCoroutine() -- it's outright missing from the docs
|
Mark M. |
what version of Kotlin are you using?
|
Abhishek K. |
1.3.72
|
Mark M. |
and what version of coroutines?
|
Sep 10 | 8:05 PM |
Abhishek K. |
lemme check
|
Mark M. |
OK, here is suspendCoroutine() in docs: https://kotlinlang.org/api/latest/jvm/stdlib/ko...
|
Abhishek K. |
So, if I use both koltin and coroutine with the latest version, it should work well?
|
Abhishek K. |
is it?
|
Mark M. |
well, I have only used suspendCancellableCoroutine() personally, as usually the APIs that I use have some sort of "cancel" semantics
|
Abhishek K. |
Okay.
|
Mark M. |
I am trying to make sense of the coroutines GitHub repo to try to determine if they removed it
|
Abhishek K. |
It seems, suspendCancellableCoroutine would work anyway, even if coroutineWorker is removed
|
Sep 10 | 8:10 PM |
Mark M. |
what do you mean by "removed"?
|
Abhishek K. |
suspendCoroutine is removed**
|
Abhishek K. |
sorry
|
Mark M. |
ah, right
|
Mark M. |
yeah, it feels like they may have gotten rid of suspendCoroutine somewhere along the line
|
Abhishek K. |
Okay.
|
Abhishek K. |
suspendCancellableCoroutine then
|
Mark M. |
I'll have to figure out what is going on with suspendCoroutine()
|
Abhishek K. |
one last thing from my side
|
Mark M. |
OK, go ahead
|
Abhishek K. |
while using suspendCancellableCoroutine, in completion callback, we can anyway resume the coroutine, what can we do in download progress callback/
|
Abhishek K. |
can we still use the same resume with progress values
|
Mark M. |
um, nothing
|
Mark M. |
a suspending function only returns one thing
|
Mark M. |
this isn't a Flow or Channel
|
Abhishek K. |
we can use setProgress(Data()) right?
|
Mark M. |
in your CoroutineWorker? it is worth a try, but I have not tried that
|
Abhishek K. |
Okay.
|
Sep 10 | 8:15 PM |
Abhishek K. |
I'm done from my side Mark. It was really great having the discussion with you.
|
Abhishek K. |
Thank You so much.
|
Mark M. |
you're welcome!
|
Mark M. |
Tad: do you have another question?
|
Abhishek K. | has left the room |
Sep 10 | 8:30 PM |
Tad F. | has left the room |
Mark M. | turned off guest access |