Skip to content
This repository has been archived by the owner. It is now read-only.

Custom RecyclerViewAdapter: MvxAndroidBindingContextHelpers.Current() is null #222

Open
sescandell opened this issue Apr 12, 2016 · 7 comments

Comments

@sescandell
Copy link
Contributor

Hi,

Steps to reproduce

  1. Clone my forked repo on branch issue-customRecyclerAdapter
  2. Run the application
  3. Go to Example RecyclerView screen

Expected behavior

The screen should display a list of items using a custom adapter (see differences here)

Actual behavior

NullReference exception is thrown

Configuration

Version: 4.1.0

What's happening

On adapter creation, the workflow is the following:

ExampleRecyclerViewFragment::OnCreateView is calling new MyCustomAdapter()

MyCustomAdapter constructor is calling its base constructor from MvxRecyclerAdapter.

MvxRecyclerAdapter constructor without any argument is calling MvxAndroidBindingContextHelpers.Current() wich is null. So further call to BindingContext.LayoutInflaterHolder property into MyCustomAdapter is crashing.

The only way to make it works right now is to explicitly set the BindingContext on call on new MyCustomAdapter() using the one from the Fragment casting it to IMvxAndroidBindingContext. Something like new MyCustomAdapter(BindingContext as IMvxAndroidBindingContext) instead of simple new MyCustomAdapter().

My concerns are:

  • Am I doing something wrong?
  • Is it normal MvxAndroidBindingContextHelpers.Current() is null?
  • Why if I don't override the Adapter, MvxAndroidBindingContextHelpers.Current() is not null during MvxRecyclerView creation?
@bspinner
Copy link

bspinner commented May 5, 2016

Did you make any progress on this? We've stumbled upon the same thing.

@thefex
Copy link
Contributor

thefex commented May 5, 2016

as workaround pass (IMvxAndroidBindingContext)Binding Context from Activity/Fragment.

@sescandell
Copy link
Contributor Author

@bspinner as suggested in my issue, for now, the only workaround I found is to use the BindingContext from the Fragment itself:

The only way to make it works right now is to explicitly set the BindingContext on call on new MyCustomAdapter() using the one from the Fragment casting it to IMvxAndroidBindingContext. Something like new MyCustomAdapter(BindingContext as IMvxAndroidBindingContext) instead of simple new MyCustomAdapter().

I didn't had time to look deeper onto that issue (and my knowledge of how binding is working behind the scene is for now to limited)

Maybe @martijn00 or/and @Cheesebaron have information about that.

@martijn00
Copy link
Contributor

I don't know why this is happening. I personally used the workaround described here before. Could you look into the source of this problem?

@bspinner
Copy link

After making sure our app isn't using too much memory, this problem vanished (for now). Some garbage collection foo?

@kjeremy
Copy link
Contributor

kjeremy commented May 24, 2016

I just hit this too. There must be something about layout inflation that is hiding this issue with the normal adapter. I know that we get the binding context here: https://github.com/MvvmCross/MvvmCross/blob/16f401378e11bc57b3ba08996e8d7ff114fdad14/MvvmCross/Binding/Droid/Views/MvxLayoutInflater.cs#L121 during inflation and it's not null (otherwise bindings wouldn't work).

Are there other cases where MvxAndroidBindingContextHelpers.Current() returns null when it shouldn't? When should MvxAndroidBindingContextHelpers.Current() NOT be null?

@kjeremy
Copy link
Contributor

kjeremy commented May 24, 2016

The stack is pushed and popped here: https://github.com/MvvmCross/MvvmCross/blob/3c735adc534a5df2d4730e9d58a08f7863c30cee/MvvmCross/Binding/Droid/BindingContext/MvxAndroidBindingContext.cs#L59-L68 during inflation.

            using (new MvxBindingContextStackRegistration<IMvxAndroidBindingContext>(this))
            {
                var layoutInflater = this._layoutInflaterHolder.LayoutInflater;
                {
                    // This is most likely a MvxLayoutInflater but it doesn't have to be.
                    // It handles setting the bindings and interacts with this instance of
                    // MvxAndroidBindingContext through the use of MvxAndroidBindingContextHelpers.Current().
                    return layoutInflater.Inflate(resourceId, viewGroup, attachToRoot);
                }
            }

This is why it works during normal inflation.

So the question is: What is the lifetime of the stack? Should MvxAndroidBindingContextHelpers.Current() return non-null while an MvxActivity is on top of the activity stack? I'm inclined to say no because we can mix with non-Mvx activities but I'm not sure.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

No branches or pull requests

5 participants