{ "id": "63636", "key": "TIMOB-3004", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [ { "id": "11243", "name": "Release 1.6.0 M10", "archived": true, "released": true, "releaseDate": "2011-02-21" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2011-04-17T02:00:39.000+0000", "created": "2011-04-15T03:34:30.000+0000", "priority": { "name": "Medium", "id": "3" }, "labels": [ "android", "cache", "defect", "imagecache", "release-1.6.0", "reported-1.6.0", "responsecache", "rplist" ], "versions": [], "issuelinks": [], "assignee": { "name": "dthorp", "key": "dthorp", "displayName": "Don Thorp", "active": true, "timeZone": "America/Los_Angeles" }, "updated": "2011-04-17T02:00:39.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [ { "id": "10202", "name": "Android", "description": "Android Platform" } ], "description": "{html}
I tested the lighthouse ticket here - \nhttps://appcelerator.lighthouseapp.com/projects/32238/tickets/1508-...\n- with the latest build from today on my Galaxy (Android 2.2). The\nimages now show up but the table performance while scrolling is\nodd.
\nUsing the KS RSS XML example: You'll see the images there but\nwhen scrolling it jitter-scrolls down slowly and then rapidly\nscrolls to the end as if it's catching up to where it is supposed\nto be. Sometimes doing a slow scroll it will stay in place or jump\nto where it should be, making it look like a scroll didn't\nhappen.
\nI'm debugging an HD ticket that is having the issue as well. I'll\nget specifics from him on how his table is performing. http://developer.appcelerator.com/helpdesk/view/67491
Tested - Android 2.2 Galaxy, Ti 1.6 CI
Anecdotal evidence provided by Q&A user in \nthis post.
\nSummary of observations/isuses with tableviews containing rows\nwith remote images:
\nAccording to user, this behavior seemed to be introduced with\n1.5.X, as tableviews in 1.4.X were fast.
Definitely not a low priority bug. A good number of applications\ntoday have a list view with images. This bug makes the app really\nslow. Could we please request you to revisit the priority of this\nbug and atleast it review it for 1.6.
\nKevin Whinery also knows about the issue given that he faced\nsimilar problems with Tweetanium. He can also provide insight into\nthis issue.
\nThank you.
@Bill, Thanks for a fabulous writeup. Truly appreciate it and\ngreat work!!
\n@Don, Given that this has been reproducible at your end & a\ngood number of us are facing it, if you could prioritize this it\nwould be greatly appreciated.
\nThanks for your support folks!
(from [135e4b8c60bd09d3cc2982b91500b870709c6e9a])\n[#3004] Introduce a few efficiencies when loading\nimages. Cache the bounds of the image source; be more selective\nwhen processProperties tries to reload an image. \nhttps://github.com/appcelerator/titanium_mobile/commit/135e4b8c60bd...
@Bill - Another input that might help you.
\nAssume there are 25 rows to be in the view - Only 5 or 6 rows\nare visible in the screen. prior to 1.5 when we were using\ndifferent classnames - only the 5 images would be loaded and the\nremaining would be fetched but would be loaded onto the screen as\nwe scroll.(Loading them as the user works! & scrolling used\nblazing fast)
\nBut with 1.5.X/1.6.X (with caching fixes we assume) all the\nimages are fetched & seem to be loaded. This can be seen\nespecially when cached.
\nIn our testing and our app, this makes a huge impact.
\nMay be you could try YQL sample(with more rows say 25) with\ndifferent ids in 1.4.x to see what we mean. 1.4.x didnt have\ncaching & had rows disappearing if you used the same\nclassname.
\nIf you still more info, we could create a sample data with our\ndata. Hope this information helps you. Thanks!
(from [316c2c7353ff133e9d0df771730ec0c9fd197ed0])\ncache image view bitmaps internally in the image view proxy when\nthey're reused inside a table view. decrease the number of fixed\nthreads for the
\ndownload manager to 2, and move the response cache cleanup to a\nsingle
\nthreaded interval based pool. [#3004]
\n\nhttps://github.com/appcelerator/titanium_mobile/commit/316c2c7353ff...
(from [1622245cb500224a86a1bd15dbfb423e62a9551d])\n[#3004] Introduce a few efficiencies when loading\nimages. Cache the bounds of the image source; be more selective\nwhen processProperties tries to reload an image. \nhttps://github.com/appcelerator/titanium_mobile/commit/1622245cb500...
(from [34fd3aead2d4e3a21197ca22142856e62809b4e6])\ncache image view bitmaps internally in the image view proxy when\nthey're reused inside a table view. decrease the number of fixed\nthreads for the
\ndownload manager to 2, and move the response cache cleanup to a\nsingle
\nthreaded interval based pool. [#3004]
\n\nhttps://github.com/appcelerator/titanium_mobile/commit/34fd3aead2d4...
We now have a two-level cache for remote images, the first level\nbeing in memory, which improves scrolling. We also removed some\ninefficiencies that were present when we load an image from the\n2nd-level cache (the Http response cache). And we got the code into\n1.6.0, which I'm very pleased about :) . That's all we'll do at\nthis time, as 1.6.0 is \"closed\".
\nPeople can check out the changes by ...
\npulling from our 1_6_X branch if you're adept at building from\nsource, or...
\ndownloading from our continuous\nbuild server
\n@Taazza: I'm not seeing that behavior. I can definitely see\n\"lower\" images (the ones I'm reaching as I scroll down) loading on\nmy way down. They definitely don't all load right away.\nThe row of a table view -- including its constituents like any\nImageViews you play plop in them -- don't come into existence into\nthey become visible. You can see this if you turn on our debug flag\nby putting setting the ti.android.debug property to true in\ntiapp.xml:
\n\n<property type=\"bool\" name=\"ti.android.debug\">true</property>
\n
\nThen at the command-line do...
\n\nadb logcat | grep \"Creating an ImageView\"
\n
\nThen open the window containing your table view. When it\nfinishes opening, count the number of grep'd lines. It will be less\nthan the number of rows in your table (assuming your table has rows\nthat extend off screen). I believe it's going to be the number of\nvisible rows plus one, but I'm not entirely certain about that.
\nAnyway try the new code, hopefully you'll see an\nimprovement.
@Bill - Sounds good. Will try it out in a couple of hours and\nget back to you with the feedback. Awesome of you to push this in\nso quickly. Cheers!
Still seeing the same issue with images that are already cached.\nWill try your steps by enabling the debug log. BTW also seeing a\ncrash:
\nSending event: exception on thread: main\nmsg:java.lang.RuntimeException: Canvas: trying to use a recycled\nbitmap android.graphics.Bitmap@4428c9e8; Titanium 1.6.0,2011/02/17\n16:34,4fd3ae...
\n[TRACE] E/TiUncaughtHandler( 331):\njava.lang.RuntimeException: Canvas: trying to use a recycled bitmap\nandroid.graphics.Bitmap@4428c9e8 [TRACE] E/TiUncaughtHandler( 331): at\nandroid.graphics.Canvas.throwIfRecycled(Canvas.java:955) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.graphics.Canvas.drawBitmap(Canvas.java:1044) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:323)\n[TRACE] E/TiUncaughtHandler( 331): at\nandroid.widget.ImageView.onDraw(ImageView.java:860) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.View.draw(View.java:6740) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1640) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1638) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1638) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.View.draw(View.java:6743) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.View.buildDrawingCache(View.java:6502) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.View.getDrawingCache(View.java:6288) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1565) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.widget.AbsListView.dispatchDraw(AbsListView.java:1365)\n[TRACE] E/TiUncaughtHandler( 331): at\nandroid.widget.ListView.dispatchDraw(ListView.java:3046) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.View.draw(View.java:6846) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.widget.AbsListView.draw(AbsListView.java:2257) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1640) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1638) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1638) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.View.draw(View.java:6743) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1640) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1638) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.View.draw(View.java:6743) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.widget.FrameLayout.draw(FrameLayout.java:352) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1640) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.View.draw(View.java:6743) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.widget.FrameLayout.draw(FrameLayout.java:352) [TRACE] E/TiUncaughtHandler( 331): at\ncom.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1842)\n[TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewRoot.draw(ViewRoot.java:1407) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewRoot.performTraversals(ViewRoot.java:1163)\n[TRACE] E/TiUncaughtHandler( 331): at\nandroid.view.ViewRoot.handleMessage(ViewRoot.java:1727) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.os.Handler.dispatchMessage(Handler.java:99) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.os.Looper.loop(Looper.java:123) [TRACE] E/TiUncaughtHandler( 331): at\nandroid.app.ActivityThread.main(ActivityThread.java:4627) [TRACE] E/TiUncaughtHandler( 331): at\njava.lang.reflect.Method.invokeNative(Native Method) [TRACE] E/TiUncaughtHandler( 331): at\njava.lang.reflect.Method.invoke(Method.java:521) [TRACE] E/TiUncaughtHandler( 331): at\ncom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)\n[TRACE] E/TiUncaughtHandler( 331): at\ncom.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)\n[TRACE] E/TiUncaughtHandler( 331): at\ndalvik.system.NativeStart.main(Native Method) [TRACE] E/AndroidRuntime( 331): FATAL\nEXCEPTION: main [TRACE] E/AndroidRuntime( 331):\njava.lang.RuntimeException: Canvas: trying to use a recycled bitmap\nandroid.graphics.Bitmap@4428c9e8 [TRACE] E/AndroidRuntime( 331): at\nandroid.graphics.Canvas.throwIfRecycled(Canvas.java:955) [TRACE] E/AndroidRuntime( 331): at\nandroid.graphics.Canvas.drawBitmap(Canvas.java:1044) [TRACE] E/AndroidRuntime( 331): at\nandroid.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:323)\n[TRACE] E/AndroidRuntime( 331): at\nandroid.widget.ImageView.onDraw(ImageView.java:860) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.View.draw(View.java:6740) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1640) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1638) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1638) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.View.draw(View.java:6743) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.View.buildDrawingCache(View.java:6502) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.View.getDrawingCache(View.java:6288) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1565) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/AndroidRuntime( 331): at\nandroid.widget.AbsListView.dispatchDraw(AbsListView.java:1365)\n[TRACE] E/AndroidRuntime( 331): at\nandroid.widget.ListView.dispatchDraw(ListView.java:3046) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.View.draw(View.java:6846) [TRACE] E/AndroidRuntime( 331): at\nandroid.widget.AbsListView.draw(AbsListView.java:2257) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1640) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1638) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1638) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.View.draw(View.java:6743) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1640) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1638) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.View.draw(View.java:6743) [TRACE] E/AndroidRuntime( 331): at\nandroid.widget.FrameLayout.draw(FrameLayout.java:352) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.drawChild(ViewGroup.java:1640) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewGroup.dispatchDraw(ViewGroup.java:1367) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.View.draw(View.java:6743) [TRACE] E/AndroidRuntime( 331): at\nandroid.widget.FrameLayout.draw(FrameLayout.java:352) [TRACE] E/AndroidRuntime( 331): at\ncom.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1842)\n[TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewRoot.draw(ViewRoot.java:1407) [TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewRoot.performTraversals(ViewRoot.java:1163)\n[TRACE] E/AndroidRuntime( 331): at\nandroid.view.ViewRoot.handleMessage(ViewRoot.java:1727) [TRACE] E/AndroidRuntime( 331): at\nandroid.os.Handler.dispatchMessage(Handler.java:99) [TRACE] E/AndroidRuntime( 331): at\nandroid.os.Looper.loop(Looper.java:123) [TRACE] E/AndroidRuntime( 331): at\nandroid.app.ActivityThread.main(ActivityThread.java:4627) [TRACE] E/AndroidRuntime( 331): at\njava.lang.reflect.Method.invokeNative(Native Method) [TRACE] E/AndroidRuntime( 331): at\njava.lang.reflect.Method.invoke(Method.java:521) [TRACE] E/AndroidRuntime( 331): at\ncom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)\n[TRACE] E/AndroidRuntime( 331): at\ncom.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)\n[TRACE] E/AndroidRuntime( 331): at\ndalvik.system.NativeStart.main(Native Method) [TRACE] W/ActivityManager( 61): Force\nfinishing activity\ncom.test.go/org.appcelerator.titanium.TiActivity
(from [00031c56940152ffde9ffd59f7a930a71ae0fb31])\ndon't overzealously recycle bitmaps that we're reusing from network\nsources, fixing a runtime error [#3004]
\n\nhttps://github.com/appcelerator/titanium_mobile/commit/00031c569401...
(from [929334e270c137a8839117a90f513e8ba423b75c])\ndon't overzealously recycle bitmaps that we're reusing from network\nsources, fixing a runtime error [#3004]
\n\nhttps://github.com/appcelerator/titanium_mobile/commit/929334e270c1...
@Bill: So here's how things stand, you idea of using adb logcat\nwas very helpful. The issue seems to be not of images but of use of\nappendRow. Scrolling doesnt happen when you use appendRow instead\nof setData. We have been able to reproduce the issue with your\nYQL_FLICKR example, pls find the gist below
\nhttps://gist.github.com/4c226b378d20ec7f76ef
\nThe same code used to work in 1.4.X. We also trying to double\ncheck the same at our end. Will post an update soon. Meanwhile if\nyou have more insight into this problem pls let us know.
@Bill One cant scroll till entire table is loaded when using\nappendRow and scrolling seems sluggish when compared to setData.\nCan be reproduced with the YQL_FLICKR sample as well.
\nOne could always use setData but perceived performance is no\ngood. A good number of fixes have gone in 1.6.X. Unfortunately we\ndont have access to 1.4.1 which is where we saw the performance of\nscrolling the same table.
\nLook forward to hearing from you.
closing resolved against KS RSS XML test case behavior, GA build\ngalaxy tab (2.2.2) and G1 (1.6).
\nTaazza, it's best to use helpdesk/Q&A for any issues you are\nencountering.