I am rendering a webview on button click and am using the shouldInterceptRequest to intercept requests to resources like images, css and js files and serving them locally instead of over the network. I expected to see a considerable amount of difference in the load time but it reduced only by a small fraction. Is it possible to parallelize the shouldInterceptRequest ?Are there any other suggestions.
Thanks in advance
The new Chromium WebView present in KitKat will read multiple InputStreams returned from shouldInterceptRequest in parallel. The Classic WebView implementation present in previous versions of Android would perform the reads serially and there is no way around that.
Without knowing the details of the content you're trying to serve it's hard to offer specific suggestions. How are you measuring this? Maybe the total time to display went down, but you perceive the load as being slower because only one thing is loading at a time? You should also try experimenting with what to cache locally - maybe the biggest gain is from only having the biggest file be served via shouldInterceptRequest?
If you can afford the extra memory usage you could store your resources in memory (by reading them into a string, for example) and serve them to the WebView using a ByteArrayInputStream. It would be ideal if you could predict what the next required resource would be (that way you'd need less memory).
Note: the Classic WebView would use shouldInterceptRequest "under the hood" for reading file:///android_asset and content: scheme resources, so there is no benefit in transferring between any of those, however doing so (specifically using the file:///android_asset/) might simplify your code.
Related
Hi i'm trying to make my HTML webpage offline for android and IOS devices. My problem is that I need to store a lot of data. This data (css,js,images,html) needs to be persistent. (even after shutdown of the device)
USE: Someone types the URL and gets the whole page offline available.
What is the best way to persist your data? and is it possible without making a hybrid or native app, just with caching and maybe appcache/indexeddb.
EDIT: i have found that indexed db in combination with dexies my best guess is for a solution. are there any do's or don'ts, alternatives or tutorials you guys suggest ?
depending on the application personality I sometimes render the entire site/application in the service worker when the service worker is installed/activated.
I wrote about an example app I did last October for a conference, https://love2dev.com/pwa/pubcon/
As far as strategy, I vary things. For data (think JSON) I tend to cache in IndexedDB (I like localforage b/c it is simple).
For site assets (HTML, JS, CSS, Fonts and often media) I use service worker cache.
If a site is heavy on media, I persist images and video in IDB b/c iOS limits service worker cache to 50MB. 50MB should be more than enough for any web application core assets as they should really be measured in kb, not MB anyway.
iOS gives you several GB of IDB storage, depending on how much disk space is available on the device.
I have built multiple SAAS apps using this strategy and never hit data quotas. Of course lots of video or images will of course consume more space and you need to watch for quota exceeded errors.
Users will also be prompted to give permission for extended storage as well, so be aware of that barrier as you may need to educate the user about this.
I'm using Jake Wharton's DiskLruCache lib.
I'm curious about app performance, caching strategy, using caching both in a view and across a whole application. Most of the time, the image won't change.
Let's say for example I have a 320x320 photo on my server. I open the stream, save the image.
In my list views, I show bitmaps and in the detail, I show a larger image. Should I save a thumbnail bitmap too? Is that more efficient?
What is your experience with sharing the cache "object" across the entire app (let's say I have multiple views that might leverage the same data. What are the issues with this?
For the sake of performance and currency, what if the image changes on the server. What's the best strategy to know that it's changed? I don't have access to modified date. Only size and yet, I don't really want to query size every time either. Set a flag in the app on the server and then query the flag?
In a traditional application (if there is such a thing), what's the best practice for clearing the cache from time to time? (indent weirded out.)
(I was inspired to write this after seeing all of the performance improvements by Facebook in iOS. I don't have billions to do caching but I would like to at least be smart about it! LOL)
A lot of these answers depend on the type of app you're writing, how important image updates are (and how likely images will change, etc), and total images produced. Aside from disk caching, you should be using memory caching as well, especially in ListViews and other areas where the same images will be scrolled through repeatedly. Look at LruCache and read the Caching Bitmaps entry from Google.
320x320 is probably too big for a listview, you will likely want to create thumbnails (depending on device, and how you're implementing your listviews).
1) You should be using Disk caching fairly aggressively (how you define that is up to the app you're writing). Use the external storage directory, and if they have a few GB left over, it's not an issue if you take 100 mb for your app for instance. It can all be cleared away if it's ever needed anyway.
2) There shouldn't be an issue. Disk IO (even to a flash medium) should never be handled on the main thread. Use AsyncTasks to load the images. There can only be one main foreground activity at once anyway, and while an activity is sleeping, it shouldn't be trying to read from the disk anyway.
3) Again this depends on how you're implementing your app. You should be able to get additional information when retrieving the file (even Apache can tell your app the last modified date).
3.1) You can have a sqllite db that keeps track of how often certain images are used, and most recent read. If the most recent read is a few days old, let that image expire.
Edit: There's a library from Jake Wharton now called Picasso that I would recommend using, which handles the Network/local IO as well as memory and disk caching. Check it ou here: http://square.github.io/picasso/ . A lot of what you will need to do can be accomplished with one line: Picasso.with(this).load(imageFileURL).into(imageView);
Is there a faster way to display Jsoup elements onto android apps?
The app I am working on download and parses a page using jsoup, gets a section of the page I want to display, edit some parts of it, then converts that section's element to HTML and displays it onto a webview.
Is there a faster way to do this? I noticed that getting the HTML from the elements takes a long time. Is there a way to directly add the element onto webview or something else without having to acquire its HTML?
Unfortunately, what you're experiencing is a side effect of trying to do (relatively) complex processing on a mobile device. Keep in mind that your app may be installed on low-resource devices and stuff like this screams low ratings.
Having said that, you usually want to do these sort of complex transformations on the server side, and then send the (formatted) data to the device - which you can then render in your WebView, for example. There is no inherent way to make jsoup faster - you're only limited by the resources of your device (as you already found out).
I am using flash builder to make an app for android/ios.
How would you recommend I use assets such as images and sounds. Should I embed them or use loader?
Any benefits to each one.
I have a fair amount of assets.
I am no expert on flash, but I ended up embedding the resources. The ease of compile-time resource checking. You just need to be sure to load each images/sounds when you have enough time to do so between frames.
For mobile apps embed is just easier. You don't need to worry about accessing the file system and purchasing/downloading is easier since you are not bundeling anything with it. The initial download will be about the same size unless you were planning on loading the assets to the device at runtime from the web. I would caution against that unless it was absolutely necessary. My experience is user are accustomed to a large download, but but load time of the app each time it opens should be minimal.
I also like that FlashBuilder will check your embed code and make sure the file is present and spelled correctly - one less thing to worry about
I'm building an app that fetches XML from a server, then parses it (it's DIDL formatted in places). The goal is to load as much into memory as possible to make it easier for users to browse (so as to enable fast scrolling through results), but I keep getting OutOfMemoryErrors. I'm kind of new to Android, and it seems like the VMs are really finicky about things. I'm loading no more than a megabyte of XML, and pretty much discarding it right away. What should I do to prevent these errors from happening?
Should I load chunk by chunk of the file over the network, write it to disk, then load chunk by chunk back into and out of memory, parsing everything into POJOs? If it can be avoided, I'd like to not have to implement some form of pagination, as per the Twitter app (it used to load more entries when you hit the bottom, it now loads a lot all at once and likewise crashes with an OOM error.) I'm running a Nexus One if that helps, CM7/Android 2.3.3.
You can read this nice article about XML parsing on Android. Using pull parser would be good choice for you, since it does not need to read complete document into the memory, which is the problem in your case. I would suggest that you store parsed results into the database, since once they are there, you can quickly do list them and page them any way you want, and performance of the DB is great. This way, you need to do loading of complete data from server to DB just once (if data is not changing on the server) or to load it once and then to get updates from time to time if it is changing (like in case of twitter).
Move all your object declarations out of loops and nullify them after the use. And use System.gc() frequently (beleive me, it works). Use class level objects as less as you can. Execute your app and keep watch on the Logcat logs.