i have an appwidget which starts an activity as user clicks it.
In my Activity i have a gridview containing relatively small Drawables(Images, because drawable could be mor than just Images) but user can size them.
I noticed that it takes too Long to size them at runtime when Scrolling trough the gridview.
I want to prepare an lruCache only one time in my appWidget's onUpdate which is called at the very beginning when the user places the appwidget on the Screen.
The problem
When i define an lruCache in my appWidget with
private final int lruCacheSize = (int) (Runtime.getRuntime().maxMemory()/1024);
private LruCache<String, BitmapDrawable> myLruCache;
...
myLruCache = new LruCache<String, BitmapDrawable>(lruCacheSize) {
#Override
protected int sizeOf(String key, BitmapDrawable value) {
// TODO Auto-generated method stub
return super.sizeOf(key, value);
}
};
Will it only exist as Long as the process exist of the appWidget? Or does the Cache-File from lruCache stays in my cacheDir of my app? Or will it be deleted after the process of the appWidget is finished? If it does exist over the process-lifetime of my appWidget, how can i Access it from my Activity?
I don't want to create everytime the user clicks on the appWidget a LruCache and fill it up with all the relatively small Images the gridview will Need later. I want to do it once, or if user clears the Cache which will be checked every hour(to save battery).
The Question
How can i achieve that? Or is there a much better/ simpler way.
Time is not really (if it happens once at the very beginning) the Problem, i notify the user that the Cache is being prepared when placing the appWidget on the Screen.
Any help is appreciated.
Update regarding CommonsWare answere
Use Traceview to determine specifically why your implementation is slow.
The app Scrolling is slow because i provide three sizes (small, medium, large) and i scale them at while Scrolling trough my gridview.(Because it would take several seconds to scale them once at activity Startup, so i don't want that).
See here what i do in my imageview which will later Show the drawable(which is an appIcon):
android:scaleType="fitXY"
android:adjustViewBounds="true"
This causes the lag because i do this for everyimage depending if selected scale size is small medium or large.
There is no "Cache-File" in your code.
So then i i'm misunderstanding something. Doesn't the lruCache create an Cache-File in the Cache-Directory of my application? If not how does in works?
First, you cannot force the user to install the app widget. Work on solving the actual performance problem, rather than trying to build some optimization that will not help all users.
My "app" is only an appwidget. There is not appIcon like at FaceBook. It is only an appWidget when he doenloads my app. Which starts an activity when you click on the button.
Second, your process can readily be terminated milliseconds after onUpdate() completes. Do not fill a cache, only to have it never be used.
I want to use the Cache which i want to fill with the Drawables in the onUpdate of the appWidget, and then i want to use These Drawables from the Cache in my activity. So i don't understand why i never would use the Cache? Maybe i'm misunderstanding something.
Picasso would give you better performance from the user's standpoint.
Does it fit my Needs after the update right now?
---------------------------------------------------------------------------------------------
Update 2
Since the scaling should be done by the GPU and take microseconds, I have difficulty believing that is your problem. What specifically did Traceview show you that made you think that scaling has something to do with this?
I noticed that the Scrolling is very fluid at medium size because that's nearly the origin size of the appIcon from the PackageManager. If scroll trough large, where only 2 or 3 appIcons are displayed per row (at medium there are 5 or 6 displayed but it is much more fluid)m it lags. (With the same logic behind it). So the only Logical answere can be scaling in the XML at the ImageView. As i commented that XML-Scaling out and scaled the appIcons to the size Large and put them directly scalled to to my Adapter for GridView it runs really smooth( Only one or to really small lags at the beginning because convertView is null??)
onUpdate() will be called much more frequently than the user will actually use your app widget.
That's right after every onclick or at the specified time. But i check if the Cache has been cleared or not, if not don't Change anything, if so load Drawables to Cache.
I noticed that it takes too Long to size them at runtime when Scrolling trough the gridview.
Use Traceview to determine specifically why your implementation is slow.
Will it only exist as Long as the process exist of the appWidget?
It will only exist for the lifetime of the process of your app.
Or does the Cache-File from lruCache stays in my cacheDir of my app?
There is no "Cache-File" in your code.
I don't want to create everytime the user clicks on the appWidget a LruCache and fill it up with all the relatively small Images the gridview will Need later. I want to do it once, or if user clears the Cache which will be checked every hour(to save battery).
First, you cannot force the user to install the app widget. Work on solving the actual performance problem, rather than trying to build some optimization that will not help all users.
Second, your process can readily be terminated milliseconds after onUpdate() completes. Do not fill a cache, only to have it never be used.
Or is there a much better/ simpler way.
Use Traceview to determine exactly where your problem lies. Then, solve that problem. For example, the problem could be that you are loading these images on the main application thread, and using a library like Picasso would give you better performance from the user's standpoint.
The app Scrolling is slow because i provide three sizes (small, medium, large) and i scale them at while Scrolling trough my gridview
Since the scaling should be done by the GPU and take microseconds, I have difficulty believing that is your problem. What specifically did Traceview show you that made you think that scaling has something to do with this?
Doesn't the lruCache create an Cache-File in the Cache-Directory of my application?
No.
If not how does in works?
It is an in-memory cache.
So i don't understand why i never would use the Cache?
onUpdate() will be called much more frequently than the user will actually use your app widget.
Related
I'm using Android-Universal-Image-Loader in a ListView of mine and I'm trying to find the best solution to following:
using resetViewBeforeLoading is necessary or else I get the same image in my ConvertViews, but this causes jitter, unless..
I use PauseOnScrollListener which is otherwise great, except that it shows a blank in some ConvertViews even for images that are already downloaded (I'm using memory and disk caches), so it's confusing to the user who sees a blank for an image they saw only 2 swipes ago
So it seems that I can't get an instant image load (for already-downloaded images) on scroll without jitter, even for images in memory, is this about right? Is there a better or more standard way to do this? (Vertical list-view showing screen-width images, sort of like the Instagram app, which does it buttery-smooth)
Otherwise, is there a way to lengthen the number of convertViews in my ListView to prevent unnecessarily aggressive re-use?
Thanks in advance
I am bulding up a grid of images for an app I'm building. It works like so:
Build up a list of Image IDs, which I must query using a different content provider each (these are images from MMS threads)
Create new activity, which hosts an ImageGridFragment. This fragment has a custom adapter that takes the grid of images, and loads each one as a bitmap asynchronously.
After images are loaded, they are cached in an LRU cache so I don't need to run unnecessary computation
So far, everything works quite well. However, I would like to pre-buffer images so that when the user scrolls down, s/he doesn't have to wait for images to load. They should already be loaded. The stock Android Gallery accomplishes. I've had a look at the source, but think there must be a more straightforward way.
To answer members' questions
Images are loaded one by one using the content://mms/part/xxx, where xxx is the ID of an image. These are MMS images, and to my knowledge, cannot be loaded as a batch process (though, maybe I'm wrong). I use a content provider in an AsyncTask to load each image
I've tried the following:
Pre buffer 30 images or so right when the fragment is created. This is not ideal because the massive I/O request, actually prevents the on-screen images from loading quickly (but the buffering does work well!)
Detect when the requested view to load is at the very bottom-right hand corner of the screen, which could work, but then would fail in the case that the GridView takes up only part of the screen. It also seems like there should be a cleaner way to do this
Thought about, but did not try, an OnScrollListener, but this will not pre-buffer images until I start scrolling, which is not ideal
So, my questions are:
Is there a good way to detect when the last GridView item is requested to load? I found that the GridView.getlastvisibleposition() method is not useful here, because it is actually returning the last element for which Adapter.getView() has been called for. If I can do this accurately, I can launch the buffer request at that time
Is there a better way to do this?
you can do right this
if(GridView.getlastvisibleposition() = mAdapter.count()-1)
how you load the images?
is it from URL or from sdcard?
are you using a image loader library?
I need some help,
I am creating an app, and want it to run faster I mean when the app is started first it shows a blank white screen for o 1-2 seconds and then loads images. I have a layout background image, and 4 imageviews which are clickable and take you to the next activity. I read somewhere i should use threads to load images and it will load them on a separate thread faster, but i have some problem using it.
So here are the problems and android studio explanations:
Thread thread=new Thread(
public void run(){
ImageView tipka=(ImageView)findViewById(R.id.tipkaproba);
tipka.setImageResource(R.drawable.instructions);
LinearLayout asd=(LinearLayout)findViewById(R.id.layoutproba);
asd.setBackgroundResource(R.drawable.backfround123);
}
).start();
Now the android studio says:
After
"Thread(" )expected
Before
"public void run(){"
; expected
On ").start();"
Invalid method declaration; return type required, Missing method body, or declare abstract.
Now i would like to know:
Does this speed up loading images, ( if not how to do it then)
How to fix my errors.
Thanks anyway !
Do all images fit in the screen?! If users need to scroll to view other images why load all of them at once? Use a grid view with adapter to load the image. In this way when the app start only images on the screen will be loaded and then when the user scrolls other images show up!
another thing you can do is to have 2 version of each image. one low quality with small size that loads first and one for high quality image. that will load latter. You can also calculate the base color for each image (use open source code or do it manually). then set the background image of iamgeview to this color. So when the image finally loads on the screen. The difference is not as dramatic as it was before.
If you want to use thread try AsyncTask first. Using AsyncTask is simpler than defining thread yourself.
Try to decrease the size of your images! If you be able to do this. it works better than any other trick! It's mobile, you don't have to show supper high quality images. users don't even notice most of the time
You probably took care of this but it worth mentioning that you need to provide different images for different screen densities and it's critical for performance as well as quality.
Hi guys i am new to android and i posted a question a week ago in this link which basically stated that i was getting a java.lang.outofmemory error when i was using a lot of different backgrounds for my activities.
why am I getting errors when I use different backgrounds in xml
So as a new developer I have searched and searched for a solution as to how to clear the memory as i go from activity but none have been clear or precise. Then i stumbled across this site http://androidactivity.wordpress.com/2011/09/24/solution-for-outofmemoryerror-bitmap-size-exceeds-vm-budget/
which described exactly what i was going through except they use 10 activities and i am only using 4. However when i implemented his code it my project i ended up with null pointer exceptions and after fiddling with his code I ended up back were i started with the same out of memory error.
So can anybody direct me to someone who can show me how to have as many backgrounds as i want with out running out of memory. Or does android as great as it is does not let you simply use more than a certain amount of backgrounds? help?
It's not that there is a limit on the amount of backgrounds, but each background image you load is a loaded into memory as a bitmap and held there until the activity is destroyed. If you are opening multiple activities one after another, each background image will need to be held in memory and so eventually you will get an out of memory exception.
If you set a large background image, you will also experience some blocking on the ui thread, while the image is loaded into memory.
One way around this that worked for me was to use an imageloader. This decodes the image off the ui thread, caches it on disk, loads it into memory and if memory is running low, will clear an image from memory and fallback to the disk cache. You may get a slight delay/fade in as the image is loaded but this is not so bad visually, and when loaded once, will load straight away if you go back to that activity.
Check out Picaso Picasso which is really easy to implement and a great api or Universal Image Loader.
My layouts were all RelativeLayouts and the first child (will be behind all other views) was an ImageView with scaleType centercrop and width and height set to match_parent. When each activity loads (onCreate), just grab a reference to the imageview in your layout and set the required background image using your ImageLoader of choice.
The other option is to have multiple copies of your background image in your resources, with each one resized to perfectly fit your resolutions of choice (drawable-mdpi/-hdpi/-xhdpi etc). This way, you ensure you are never loading images that are way bigger than you need to be displayed and your app will be more forgiving in terms of memory consumption.
I have been looking for a solution and I found many different opinions to solve my problem.
Here is what my app is doing:
It does a search in a database and it assembles n screens with n pictures. Each picture is an ImageButton and each one has its own image, action, etc. depending on what is stored in the database.
The created screens are thrown inside of a ViewFlipper.
Some items have "children".
So, if a user clicks on an ImageButton with a "child", it will search the database, get items, assemble the new screen(s) with ImageButtons with informations from database.
Then, Add this (these) new screen(s) to the ViewFlipper and keep a reference from the caller screen, so user may return to the caller screen if he wishes.
It will do the item 3 whenever an ImageButton has "children" according to the database.
It's easy to see that there will be lots of screens in the initial ViewFlipper.
It works flawlessly in my Asus EEE Pad Transformer. However if I try to run it in my Galaxy S (less memory) it will eventually crash (lack of memory exception) if I keep on browsing screens.
What's the best way for me to free up memory in this situation?
It is probably not going to be easy, but if you want to save memory - save on the views. Instead of building all the views in advance, build only the ones you need, and manage the flipping manually. After all, you only need to show one image at a time, so prepare that, and perhaps the one before that and the one after that for quick flipping, but don't prepare everything else before needed.