Code Monkey home page Code Monkey logo

Comments (12)

esilverberg avatar esilverberg commented on June 29, 2024 1

Hi Gang,

I believe I have identified the cause and a solution to the issue of Picasso triggerring continuous calls to the getView method of the adapter.

First, the issue (for me) only arises when I use the .fit() method with Picasso. This method causes Picasso to wait until the ImageView is loaded, and dimensions are obtained, before making the network/in-memory call(s) necessary prior to calling setImageDrawable.

One of the idiosyncrasies of setImageDrawable on an ImageView is that it triggers an onMeasure and onLayout, according to this SO post.

If you were to avoid using the .fit() method, the call to Picasso.load.into would also call setImageDrawable and call requestLayout, but calls to requestLayout in the middle of a layout pass have no effect. However, if you defer the call to setImageBitmap, then you end up in a cycle where a layout pass is calling getView, which is calling Picasso, which does a deferred setImageBitmap, which (a few ms later) requests a layout pass, ad infinitum.

Why does this work normally with ListViewAdapters? I am not entirely sure, but something in this Swipecards implementation of onLayout is causing it to constantly create new views. I suspect that ListViewAdapters know how to "recycle" views, so that if you have a ListView of 5 items laid out, and you call onLayout, it won't re-create 5 views but will instead re-use the 5 views on screen and thus avoid triggering Picasso again.

Regardless - I have a proposed fix. In the nominal case, onLayout is repeatedly called until there is both an active and top card, meaning we end up in this code here:

if(mActiveCard!=null && topCard!=null && topCard==mActiveCard) {
    removeViewsInLayout(0, LAST_OBJECT_IN_STACK);
    layoutChildren(1, adapterCount);
}else{

This code has the effect of re-laying out the cards behind the top card, and is necessary for cards in the back to be aligned properly as the card in the front is moving, in the event that they interact. If you aren't actively dragging or manipulating the top card, you don't need to do anything with the layout, because the code just below will have already taken care of it. Thus, we need a new method to detect when the user is actively manipulating the top card. I added this code to FlingCardListener.java:

public boolean isTouching() {
    return this.mActivePointerId != INVALID_POINTER_ID;
}

public PointF getLastPoint() {
    return new PointF(this.aPosX, this.aPosY);
}

And then changed SwipeFlingAdapterView.java, lines 104-105, to this:

if(mActiveCard!=null && topCard!=null && topCard==mActiveCard) {
  if (this.flingCardListener.isTouching()) {
    PointF lastPoint = this.flingCardListener.getLastPoint();
    if (this.mLastTouchPoint == null || !this.mLastTouchPoint.equals(lastPoint)) {
      this.mLastTouchPoint = lastPoint;
        removeViewsInLayout(0, LAST_OBJECT_IN_STACK);
        layoutChildren(1, adapterCount);
    }
  }
}else{

I also added PointF mLastTouchPoint as a member variable. Per this change for me, this will now only call getView when the user is actively moving the top card or at Activity onCreate.

Cheers!

from swipecards.

alopix avatar alopix commented on June 29, 2024

Can you describe this issue in more detail? Did not encounter this issue or maybe just didn't notice yet?!

from swipecards.

qichuan avatar qichuan commented on June 29, 2024

I am using Universal Image Loader, and it is working fine with SwipeCards.

from swipecards.

sanderversluys avatar sanderversluys commented on June 29, 2024

I'm receiving OutOfMemory crashes on Google Play during beta testing of an app with your (awesome) library.

I'm also using Picasso to set card backgrounds in getView from adapter.

You have any suggestions how to prevent this? Txn.

(Report from Samsung Galaxy S4 with Android (4.4)

android.view.InflateException: Binary XML file line #17: Error inflating class
at android.view.LayoutInflater.createView(LayoutInflater.java:626)
at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
at android.view.LayoutInflater.onCreateView(LayoutInflater.java:675)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:700)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:761)
at android.view.LayoutInflater.inflate(LayoutInflater.java:498)
at android.view.LayoutInflater.inflate(LayoutInflater.java:398)
at be.accentjobs.swop.ui.MainActivity$JobAdapter.getView(MainActivity.java:408)
at flingswipe.SwipeFlingAdapterView.layoutChildren(SwipeFlingAdapterView.java:122)
at flingswipe.SwipeFlingAdapterView.onLayout(SwipeFlingAdapterView.java:109)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1055)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1677)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1531)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1440)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2284)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2004)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1236)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6471)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:803)
at android.view.Choreographer.doCallbacks(Choreographer.java:603)
at android.view.Choreographer.doFrame(Choreographer.java:573)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:789)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.constructNative(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at android.view.LayoutInflater.createView(LayoutInflater.java:600)
... 44 more
Caused by: java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:677)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:507)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:872)
at android.content.res.Resources.loadDrawable(Resources.java:3056)
at android.content.res.TypedArray.getDrawable(TypedArray.java:602)
at android.widget.ImageView.(ImageView.java:133)
at android.widget.ImageView.(ImageView.java:123)
... 47 more

from swipecards.

qichuan avatar qichuan commented on June 29, 2024

Hi niob,

I have solved this problem in my pull request, pleasee see below link.
#15

from swipecards.

sanderversluys avatar sanderversluys commented on June 29, 2024

I'll remove my previous comment because that's not related to the Picasso issue. But thanks @qichuan for the tip!

from swipecards.

Diolor avatar Diolor commented on June 29, 2024

OutOfMemory is usually a sign of memory leak. The problem is that picasso looks like it creates an infinite loop when interfering with async tasks (infinite calls of requestLayout).

Sorry guys but I cant help these days much. Will help after a week or so that i will be back on track.

from swipecards.

kamoljan avatar kamoljan commented on June 29, 2024

Any update on this issue?

from swipecards.

Diolor avatar Diolor commented on June 29, 2024

Not really. I would be glad to review a pull request however if someone digs into that.

from swipecards.

wtttc avatar wtttc commented on June 29, 2024

Same problem (getView continuously) when using android query or universal imageloader

comment out 2 lines below in SwipeFlingAdapterView seems do some help

...
  if (mActiveCard != null && topCard != null && topCard == mActiveCard) {
//                removeViewsInLayout(0, LAST_OBJECT_IN_STACK);
//                layoutChildren(1, adapterCount);

            } ...

from swipecards.

simllll avatar simllll commented on June 29, 2024

The last comment fixes the issues for me too! Can someone fix this in the main rep? Would be awesome :)

regards
Simon

from swipecards.

sacdulanga avatar sacdulanga commented on June 29, 2024

thank u @esilverberg bro. U save my day (Y) 🥇

from swipecards.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.