Apr 26 | 7:20 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Apr 26 | 7:30 PM |
jth | has entered the room |
Mark M. |
hello, jth
|
jth |
Hello
|
Mark M. |
how can I help you today?
|
jth |
Just joined today
|
jth | |
jth |
I have a hybrid Android App, webview and native views
|
jth |
I am having issues with Volley and sending the cookies from the webview via Volley to API calls
|
Michaelidle | has entered the room |
Mark M. |
"However on my volley calls to the APIs, the cookies are not being sent" -- are you doing something to get the cookies over to Volley?
|
Mark M. |
(BTW, hello Michaelidle -- I will be with you shortly!)
|
Mark M. |
jth: I don't recall Volley having its own cookie code, though I wasn't paying much attention to that when I last looked at the Volley source
|
Mark M. |
Volley delegates HTTP I/O to HttpURLConnection on Android 2.3+
|
jth |
Well first of all, is volley still recommended?
|
Mark M. |
well, it's better than using HttpURLConnection directly
|
jth |
I recently added it to the app, however is seems like documentation is lacking
|
Mark M. |
dental surgery is better than using HttpURLConnection directly
|
Mark M. |
personally, I would lean towards OkHttp3
|
Mark M. |
for the documentation and support reasons, plus packaging
|
Mark M. |
but Volley is OK
|
jth |
I was looking into that and retrofit
|
Mark M. |
Retrofit blends nicely with OkHttp3
|
jth |
most api calls are json and in house apis
|
Mark M. |
anyway, HttpURLConnection knows nothing about android.webkit.CookieManager AFAIK
|
jth |
ok
|
Mark M. |
it has its *own* CookieManager class (java.net.CookieManager)
|
Apr 26 | 7:35 PM |
Mark M. |
so if you are going to synchronize cookies, AFAIK you have to do that yourself
|
Mark M. |
I haven't looked into the details of exact mechanisms for that
|
jth |
Is seems like many people recommend a persistent cookiestore, but not many examples of that
|
Mark M. |
persistence is a separate issue
|
jth |
Yes I need to maintain the cookies between the webviews and apis calls and store them
|
Mark M. |
since there are cookie-related APIs exposed on both sides, it seems plausible for you manually schlep cookies from the WebView side over to the HttpURLConnection side
|
Mark M. |
but, again, I haven't played with that personally
|
jth |
ok
|
Mark M. |
let me take a question from Michaelidle, and I'll be back with you in a bit
|
jth |
sure
|
Mark M. |
Michaelidle: your turn! do you have a question?
|
Michaelidle |
So I have been slowly been reworking my Adapter, ListView, Repository code. I removed all of the adding to the List<> that happened on the background thread, so that seems to work well, because now I'm not getting "the data in the adapter has changed, remember to call notifyDataSetChanged". But sometimes I still feel the need to add to that List<> backing that adapter.
|
Michaelidle |
So my question is, do you have any recommendation for modifying a List<> that could sometimes be held in an adapter and sometimes it's not.
|
Mark M. |
whoever is doing the adding needs to know if it is in an adapter or not
|
Mark M. |
I don't see much in the way of an alternative
|
Apr 26 | 7:40 PM |
Michaelidle |
Yeah, it's just that I have this Repository which you can call getList() on, and sometimes it's used in a service, and sometimes it can concurrently be used on my Activity.
|
Mark M. |
that's a scary architecture, IMHO
|
Mark M. |
I'd keep what the UI is displaying a bit more separate from what the back-end is manipulating
|
Mark M. |
for example, you could have your service still update the List<>
|
Mark M. |
however, the UI is working off of a copy of the List<>
|
Mark M. |
your service also raises an event bus event (or the equivalent) to say "hey! the master list is updated!"
|
Mark M. |
perhaps including information on what actually changed
|
Mark M. |
then, the UI can receive that event and do whatever modifications are necessary to its copy
|
Mark M. |
this is a bit on the MVVM side of the GUI architecture approaches, though I'm no expert
|
Michaelidle |
That gives me some ideas. Thanks
|
Mark M. |
the UI is working off of a view-model, while the service manipulates the real model
|
Mark M. |
let me switch back to jth, and I'll return to you in a bit
|
Mark M. |
jth: your turn! do you have a question?
|
jth |
yeah so I was prototyping with Retrofit today
|
Apr 26 | 7:45 PM |
Aaron H. | has entered the room |
jth |
If I want a sync call, do I need to do it on another thread? I was getting a onMainThread exception
|
Mark M. |
(hello, Aaron -- I will be with you shortly!)
|
jth |
I was able to use it async with calls backs, but when I want a sync call
|
Mark M. |
jth: Retrofit offers two models: synchronous or asynchronous
|
Mark M. |
basically, whether the interface-defined method returns the results or takes a Callback as a parameter
|
Mark M. |
both work, but the synchronous approach needs to be done on your own background thread
|
jth |
ok that is what I thought
|
Mark M. |
there's a pair of stone tablets somewhere; one has "thou shalt not do network I/O on the main application thread" carved into it
|
jth |
what is the current recommended way for background threads? Currently the inherited app uses classes extended from Thread.
|
Mark M. |
nothing wrong with that
|
jth |
If you talk about it in the book, you can point me there
|
jth |
ok
|
Mark M. |
I demonstrate lots of different threading approaches in the book, as one size does not fit all
|
jth |
ok i have one follow up to the cookie issue, but you can go around the room and I can wait
|
Mark M. |
OK
|
Mark M. |
Aaron: your turn! do you have a question?
|
Apr 26 | 7:50 PM |
Aaron H. |
I actually have just started the book and was wanting to check this out and see if I could glean any information from others questions
|
Aaron H. |
i don't have any specific questions...yet
|
Mark M. |
OK
|
Mark M. |
you can also peruse several years' worth of chat transcripts at https://commonsware.com/office-hours/
|
Mark M. |
this chat's transcript will be posted there shortly after the chat ends
|
Mark M. |
if you come up with a question, let me know, so I can include you in the round-robin
|
Aaron H. |
that's great! thank you
|
Mark M. |
meanwhile...
|
Mark M. |
Michaelidle: back to you! do you have another question?
|
Michaelidle |
Yeah, so I've been using an interface to listen to my Repository when a new item is added in the DB, and then my activity get's the callback, and it adds the item in my list.
|
Michaelidle |
Works well, but I am curious if I cause a memory leak in an Activity if I don't "unregister" the listener.
|
Michaelidle |
Because my Repository is a Singleton.
|
Mark M. |
if the repository can reach the activity via the listener, then yes, by default, failing to unregister will cause a leak
|
Apr 26 | 7:55 PM |
Mark M. |
the typical approach is to have the listeners held onto weakly by the singleton
|
Mark M. |
e.g., the singleton has a WeakReference<Listener> instead of a Listener
|
Mark M. |
then, the Listener (and things downstream from it, like the activity) can get garbage-collected despite the singleton knowing about them
|
Michaelidle |
That's a great way to think about it. I've actually never used a WeakReference. Does that just automatically get removed after some condition is met?
|
Mark M. |
the singleton, as part of getting the Listener out of the WeakReference<Listener>, will check for null, indicating that the Listener had been garbage-collected
|
Mark M. |
yes, if there are no strong (i.e., normal) references to the object, the WeakReference gets cleared out, so it holds null instead of the former object
|
Michaelidle |
Gotcha. But creating an unregister that happens onStop() will also do the trick... instead of a WeakReference.
|
Michaelidle |
Correct?
|
Mark M. |
yes... assuming you don't screw up somewhere and forget to unregister
|
Mark M. |
there are also edge cases, like unhandled exceptions, to consider
|
Mark M. |
so, skipping the WeakReference can be done, but you should do other things to try to watch for leaks, like integrate LeakCanary
|
Michaelidle |
So in an unregister, I would just set the Listener = null and that should be alright?
|
Mark M. |
it clears up that potential leak
|
Mark M. |
I offer no guarantees about any other potential leaks in your code :-)
|
Michaelidle |
Thanks
|
Mark M. |
jth: back to you! do you have another question?
|
jth |
My code heavily uses the Apache HTTP client. I know in 5.x Google Deprecated it, and now in 6.0 they have removed it. I am currently using useLibrary 'org.apache.http.legacy' to continue to be able to build in Android Studio.
|
Apr 26 | 8:00 PM |
jth |
I realize switching over to HttpURLConnection is recommended, but having this prioritized over other item can be difficult.
|
jth |
Is there a change useLibrary 'org.apache.http.legacy' could be pulled in the future?
|
Mark M. |
there are two separate issues:
|
Mark M. |
1. will the built-in HttpClient be removed in the future? unlikely, as that will break all sorts of legacy apps
|
Mark M. |
2. will useLibrary ... be removed, to force ongoing development off of HttpClient? I can't rule that out
|
Mark M. |
that comes from the Android Plugin for Gradle
|
Mark M. |
and so even if it is removed in some future version of that plugin, you still have time, simply by not upgrading to a newer plugin
|
Michaelidle |
I'm not Mark, but just use OkHttp. I know that's not really an answer, but it's the goto client in Android, and it's included in Android (I forget which version) by default AFAIK.
|
Mark M. |
eventually, you may start to feel the pinch from that
|
Mark M. |
Michaelidle: more accurately, HttpURLConnection starting with Android 4.4 is based on an earlier version of OkHttp3
|
jth |
ok just trying to get enough of a case to get PMs to buy into setting aside to for tech debt
|
Mark M. |
mostly to get Square's work on supporting SPDY
|
Mark M. |
jth: more so than rushing to move off of HttpClient, I would recommend that you pick one HTTP stack and stick with it
|
jth |
ok
|
Mark M. |
that could be Apache's independent packaging of HttpClient for Android, or OkHttp3, or Volley, or using HttpURLConnection directly
|
Mark M. |
or Ion or other less-common alternatives
|
Apr 26 | 8:05 PM |
Mark M. |
you're stuck with WebView being separate, but there's nothing that you can do about that :-(
|
Apr 26 | 8:05 PM |
jth |
just thought moving to volley was the right idea for APIs call, no wondering if that was the right decision.
|
Mark M. |
IMHO, OkHttp3 > Volley > HttpClient > torture > HttpURLConnection
|
jth |
And as you stated I can use OkHttp3 with retrofit
|
Mark M. |
yes, you can configure an OkHttpClient once and use that both directly (e.g., binary downloads) and with Retrofit (e.g., Web service calls)
|
jth |
ok that is a start. Just hard to make changes to a 5 year+ app in the 1,000,000 - 5,000,000 download range
|
Mark M. |
yeah, that's not going to be fun
|
jth |
and multiple developers and contractors in it before me
|
jth |
thank you for the help and advice
|
Mark M. |
you are very welcome
|
Mark M. |
Michaelidle: back to you! do you have another question?
|
Apr 26 | 8:10 PM |
Aaron H. | has left the room |
Michaelidle |
I've used interfaces in java for years. Even before I started Android development. And this ListView/Adapter/Repository issue I've been thinking about them a lot, and may have started to overthink them. I actually have no idea why they work at all. So this is me just trying to clear my head (I think I've been starring into this issue for too long). So onStart() I register a onListChangedListener() and I create an anonymous inner class. Why do the callbacks even work. Is this because of Polymorphism?
|
Mark M. |
"I actually have no idea why they work at all" -- they are stitched together by Santa's elves during the off-season
|
Mark M. |
but an anonymous inner class is just an implementation of your interface (or subclass of some other class)
|
Mark M. |
the fact that it is anonymous is syntactic sugar, to save you from declaring YetAnotherLongJavaClassName somewhere
|
Mark M. |
polymorphism in Java is enabled by interfaces
|
Mark M. |
I don't know if anything of what I wrote helped
|
Michaelidle |
Hahah. I feel like I've taken them for granted... and then they make sense... and then they don't. What caused me to go insane was, I had Repository.deleteItem() being called in an IntentService, which made the listener go off in my Activity and I would call notifyDatasetChanged(), but my code wasn't doing anything, because it wasn't on the main thread. So I was just confused, how something that was "seemingly" happening in onStart() (which I know is not the case) was happening off the main thread.
|
Apr 26 | 8:15 PM |
Mark M. |
keeping things straight with threads takes getting used to
|
Mark M. |
OK, if either of you have any questions, just chime in
|
Michaelidle |
Is it anything besides syntactic sugar? I can access things from my activity in the AIC, like the adapter, and call notifyDatasetChanged()
|
Mark M. |
well, you could do the same thing from a named inner class
|
Mark M. |
the anonymous bit is syntactic sugar
|
Michaelidle |
So if I wanted to make it a separate class (like a inner static class), I wouldn't be able to pull that off then (getting my Activitys members)
|
Mark M. |
a static class has no access to the members of the outer class
|
Mark M. |
an inner class does
|
Mark M. |
(I wish they had better names for those, but that's a separate issue)
|
Apr 26 | 8:20 PM |
Michaelidle |
My class could take some of those members in the constructor right?
|
Mark M. |
sure
|
jth |
I did find this post about cookies webview and httpURLConnection - http://stackoverflow.com/questions/36800094/and... - what is your opinion of this?
|
Mark M. |
um, that looks like the link you posted at the outset of the chat
|
Michaelidle |
Okay. Thanks Mark. You eased some of my worrying. Silly how 1 problem made me rethink ~4 years of using interfaces. Hahaha
|
Mark M. |
Michaelidle: glad I could be helpful
|
Mark M. |
jth: are you sure that's the post that you are referring to? it looks like an unanswered question that you (or somebody with your initials) asked
|
Michaelidle |
jth
|
Apr 26 | 8:25 PM |
Michaelidle |
I did something like that recently.
|
Michaelidle |
I got a cookie in my web view, that I had to push through to my okHttpClient. Let me look up my code and see what I did really quick. Maybe it'll give you some direction.
|
Mark M. |
what I was envisioning was something akin to http://stackoverflow.com/a/18061610/115145
|
Mark M. |
the comments suggest that this code would need some amount of updating to reflect changes to WebView, which was seriously overhauled in Android 4.4
|
jth | |
Michaelidle |
Mark, while I look for my code... I do have a question still regarding adapter and adding/removing/updating the items. I do want it to look fairly smooth. The way I was doing it before was replacing the whole adapter, so that sucked, but now It looks alright, but I'm not sure how updating a Convo in List<Convo> would work. My Convo objects are immutable, so I would need to remove and then add.
|
Mark M. |
jth: yeah, that's the post I was just looking at
|
Mark M. |
there's promise there, but it looks like it may need work
|
jth |
ah ok
|
Mark M. |
Michaelidle: well, if you were using RecyclerView, you would use notifyItemChanged()
|
Apr 26 | 8:30 PM |
Michaelidle |
jth I saved the cookie in my code to a pref. I guess it's a little wacky, but it works. String gotCookie = CookieManager.getInstance().getCookie(authUrl);
|
Mark M. |
off the top of my head, I'm not sure how I would handle that with ListView, sorry
|
Michaelidle |
Do you know any tips in the adapter to make it smooth? I know someone recommended hasStableIds which I haven't looked into yet.
|
jth |
thank you again
|
Mark M. |
Michaelidle: sorry, nothing is leaping to mind off the cuff, with immutable items in the adapter
|
Mark M. |
and that's a wrap for today's chat
|
Michaelidle |
I guess the smooth part is a silly question. Yeah, I think RecylclerView will be a good choice. Just curious really if there's a best bet for Adapter and ListView, but you said the next book update. So I guess I'll have to wait!
|
Mark M. |
I'm not sure what you're referring to with the next book update
|
Mark M. |
I have one due out next week
|
Mark M. |
but I don't think I have anything new related to ListViwe
|
Mark M. |
er, ListView
|
Mark M. |
anyway, the chat transcript will be posted to https://commonsware.com/office-hours/ shortly
|
Mark M. |
the next chat is Thursday at 4pm US Eastern
|
Mark M. |
have a pleasant day!
|
jth | has left the room |
Michaelidle | has left the room |
Mark M. | turned off guest access |