-
Notifications
You must be signed in to change notification settings - Fork 221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ViewBindings on subclasses broken #257
Comments
@Dellkan , Thanks for the issue report. As you are on it, is it possible for you to make a smallest sample project to demonstrate the issue? I will work on it as soon as I get time. Meanwhile, if you like, you can try to debug to locate the problem. The issue should not be too difficult to solve. Thanks, Cheng |
@weicheng113 I'll try to get time to build a minimal sample tonight. 0.8.13 -> 0.8.14 touched a lot of files, and I'm not sure where to start looking for this kind of issue (maybe you can give me a couple of pointers on where I should start looking?). To the extent I've debug-stepped through the code so far, I've noticed the following:
As an aside, these kind of deep dives into the source codes really make me wish the project had better javadocs comments (on class/method purpose, usage, etc). It's pretty hard to understand what each part in this library does from source code and class/method names alone. |
Hi @weicheng113. Please find a minimal sample on https://github.com/Dellkan/RobobindingIssue257Demo. In it, I discovered that it doesn't matter whether the binding is custom or not. No bindings will be attached on some view elements. Again, this only occurs when using While debugging, I stumbled over
Not sure if the previous snippet is relevant, but it does run through it (and returns |
https://github.com/RoboBinding/RoboBinding/blob/develop/framework/src/main/java/org/robobinding/LayoutInflaterHoneyComb.java#L158 ( I see that 0.8.14 introduced some significant changes to how the factories are wrapped and packed @weicheng113 I'm at the end of my rope. I understand far too little of how LayoutInflater with its factories work, or what considerations you have to make, or are trying to make. By debugging, it seems to me that it has something to do with how LayoutInflaterHoneyComb is setting privateFactory2, but I don't know know how I'm to fix that. I would appreciate it greatly if you could look into it |
@Dellkan, Sorry to response late. This part is a bit complicated. I spent quite a lot of time on this before. I will find some time this weekend. Thanks a lot for the issue demo and your effort into the problem. Once i have located the issue, i will get you back. Thanks, Cheng |
@weicheng113 Thank you for taking the time :) Let me know if I can be of any help |
@Dellkan , I think i located the issue. In the line 57 ~ 61 CalligraphyLayoutInflater, the code block blow: @Override
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
setPrivateFactoryInternal();
return super.inflate(parser, root, attachToRoot);
} The method setPrivateFactoryInternal() will erase the privateFactory(erased the privateFactory from RoboBinding as well), which i think it is not right thing or safe thing to do. In RoboBinding v0.8.13, we took the same approach as Calligraphy, which is subclassing of LayoutInflater(LayoutInflaterHoneyComb--subclassOf-->LayoutInflaterPreHoneyComb--subclassOf-->android.view.LayoutInflater). In this approach, CalligraphyLayoutInflater will be replaced by RoboBinding LayoutInflaterHoneyComb. That is why CalligraphyLayoutInflater will not affect RoboBinding LayoutInflaterHoneyComb. Whereas, since v0.8.14, we used a more elegant way, clone and wrap the existing LayoutInflater and we don't have any subclasses of android.view.LayoutInflater(LayoutInflaterHoneyComb and LayoutInflaterPreHoneyComb are no long subclasses of android.view.LayoutInflater). A cloned CalligraphyLayoutInflater will be used, which will erase any privateFactory previously set(in RoboBinding we never erase but wrap and delegate). In this case, I would think what Calligraphy did was not a proper approach. What do you think @Dellkan ? |
@weicheng113 Thank you very much for looking into this. I debugged through, and saw the same thing. I'm still stumbling and struggling to understand how the mechanics of LayoutInflater works (with its factories, I've reported this to chrisjenx/Calligraphy#317, hoping we can get eyes on this from both ends. Meanwhile, can you think of any workaround that either you or I can apply from Robobinding, or even in my own projects, until we get a more permanent fix? I'm using both Calligraphy and Robobinding in production settings, and can't really make do without either. |
I've forked Calligraphy, and put in a hotfix. It seems to do the trick, but I'm not sure yet if there are any side-effects (there could very well be). |
@Dellkan, I will give you my idea in a hour or so. |
@Dellkan , I had a look of your hotfix. It looks good to me. What we need to do with privateFactory is if there is an existing privateFactory, we will wrap and delegate it. I will try to explain to you my personal understanding on the mechanics of LayoutInflater here. I think the intention of these three factories: mFactory, mFactory2 and mPrivateFactory2, was to enable API consumer to plugin custom view creation abilities. mFactory is an old interface and is retained for back-compatibility. The main logic of LayoutInflater is in the method of LayoutInflater.createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
boolean ignoreThemeAttr):View If you browse through the code, it says it will try to createView
Cheng |
@weicheng113 Thank you for the description, and for taking a look at the hotfix. So, essentially, all there is to it is:
The rest of the code usually found then deals with compatibility layers, and for wrapping/delegating, since only one LayoutInflater can be set. Robobinding and Calligraphy both have to deal with mPrivateFactory because both want to do something after the view has been created, which may not have happened before in step 3. They both want to read the xml attributes and apply them to the view, but don't actually need to create the view itself Would that be a correct summary? |
@Dellkan I think your understanding is correct in RoboBinding side. I am not sure about Calligraphy. The feature #164 is a very important one to implement next. I believe It will be beneficial to RoboBinding users. If you get time and are interested, please I would like to invite you to have a look. Thanks, Cheng |
@weicheng113 I've already implemented something similar to #164 (I documented some of it in #228). This is of course in Robobinding-helpers, which in short is a layer of abstraction on top of Robobinding. I'd love to take a look at #164 to implement first-class support, but can't give any promises as to when I'd have time to do so. |
@Dellkan , Thanks a lot. I will have a look your related addition when i get time. No problem, we can contribute when we have time. We open source to join all contributions to make progress and benefit other users. |
ViewBindings doesn't seem to apply on sub-classes of views. As far as I can tell, this issue only affects custom viewbindings.
Example:
This one works
While this one will not work.
The only difference between these two layouts are
android.support.design.widget.TextInputEditText
vsEditText
.android.support.design.widget.TextInputEditText
extendsAppCompatEditText
which in turn extendsEditText
.The problem field is
bind:text
- there are no errors, but the binding is never applied to the view. Neither OneWay nor TwoWay bindings seems to have any effect. Please note that I've overwrittentext
with my own binding (see https://github.com/Dellkan/Robobinding-helpers/blob/master/robobinding-helpers-common/src/main/java/com/dellkan/robobinding/helpers/common/viewattributes/EditText/EditTextExtensions.java)Also note that I've tried with
WebView
(to test the last pull request), and had the same issue when I tried to use a subclass ofWebView
. Neither bindings that should be inherited, nor bindings applied directly to the subClass was applied.I've run some tests, and found that this issue was introduced in 0.8.14, while 0.8.13 works completely as expected (and inherits bindings correctly).
The text was updated successfully, but these errors were encountered: