Giter Site home page Giter Site logo

hi-dhl / binding Goto Github PK

View Code? Open in Web Editor NEW
423.0 423.0 48.0 369 KB

Simple API implement DataBinding and ViewBinding. 简单的 API 实现 DataBinding 和 ViewBinding,欢迎 star

License: Apache License 2.0

Kotlin 99.94% Java 0.06%
activity appcompatactivity databinding-viewbinding delegate fragment kotlin recyclerview

binding's Introduction

binding's People

Contributors

br3ant avatar hi-dhl avatar singledog avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

binding's Issues

Fatal Exception: java.lang.IllegalStateException: onGetLayoutInflater() cannot be executed until the Fragment is attached to the FragmentManager.

Fatal Exception: java.lang.IllegalStateException
onGetLayoutInflater() cannot be executed until the Fragment is attached to the FragmentManager.

androidx.fragment.app.Fragment.getLayoutInflater (Fragment.java:1673)
androidx.fragment.app.Fragment.getLayoutInflater (Fragment.java:1639)
com.hi.dhl.binding.databind.FragmentDataBinding.getValue (FragmentDataBinding.java:35)

报错 FragmentDataBinding 行数: 35,但使用的Fragment(layoutId: Int) 构造方法,

按常理:在onViewCreated() 方法后调用,

FragmentDataBinding 中第 35 行
thisRef.view == null 应该为 false,除非什么异常情况导致执行此句,

然后,想到可能和fragment 的恢复有关系,恢复的时候 走的是 Fragment() 无参数方法,layoutId = 0, 所以 view 为空

目前尝试在 onSaveInstance() 里面保存 layoutId,在恢复时重新将 layoutId 还原

所以也不全是这个库的问题,只是报错的地方在库里面而已

在Navigation启动的Fragment中使用报错

使用Navigation启动Fragment报错如下:

Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at com.hi.dhl.binding.viewbind.FragmentViewBinding.getValue(FragmentViewBinding.kt:34)
        ......
Caused by: java.lang.ClassCastException: androidx.appcompat.widget.AppCompatImageView cannot be cast to android.widget.TextView
        at fun.inaction.stallx.databinding.FragmentSearchBinding.bind(FragmentSearchBinding.java:78)
        at fun.inaction.stallx.databinding.FragmentSearchBinding.inflate(FragmentSearchBinding.java:68)
        at fun.inaction.stallx.databinding.FragmentSearchBinding.inflate(FragmentSearchBinding.java:58)
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.hi.dhl.binding.viewbind.FragmentViewBinding.getValue(FragmentViewBinding.kt:34)

报错的代码:

class FragmentViewBinding<T : ViewBinding>(
    classes: Class<T>,
    fragment: Fragment
) : FragmentDelegate<T>(fragment) {
... 省略

bind = layoutInflater.invoke(null, thisRef.layoutInflater) as T

... 省略

ActivityViewBinding 是否应该主动在onCreate时调用setContentView

ActivityViewBinding 里是在委托首次赋值时调用的setContentView,根据使用习惯的不同,会使得调用时机不明确:例如可能在数据请求返回之后才遇到首次操作UI的时机,那么在此之前委托的属性都没被获取、不会调用setContentView,使得页面一直显示空白。

对于类似的情况,是不是应该监听Activity的生命周期,主动在 ON_CREATE 事件里调用setContentView

请问如何迁移呢

请问项目从butterknife或者fvb,如何迁移过来呢?好像viewbinding一打开,所以xml就被解析了。

在BRAVH中怎么使用呢

比如在BRAVH中使用viewbind, 不会自己去写viewholder, 是直接使用adapter 提供的 BaseViewHolder, 照着文档中的例子写,编译通不过

反射调用时报NoSuchMethodException崩溃

Oppo R17
binding:1.0.7

Caused by: java.lang.NoSuchMethodException: com.datedu.lib_camera.databinding.ActivityTakeVideoBinding.inflate [class android.view.LayoutInflater]
at java.lang.Class.getMethod(Class.java:2072)
at java.lang.Class.getMethod(Class.java:1693)
at com.hi.dhl.binding.e.b(ReflectExt.kt:1)
at com.hi.dhl.binding.g.a.(ActivityViewBinding.kt:2)
at com.datedu.camera.ui.TakeVideoActivity.(TakeVideoActivity.kt:2)
at java.lang.Class.newInstance(Native Method)
at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:95)
at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:1)
at android.app.Instrumentation.newActivity(Instrumentation.java:1251)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3399)

同一类型的多个 fragment 实例的 binding.view 引用错位问题

代码结构:
Activity -> 上下两个 Fragment (同一个类型的,2个实例)

具体使用:

class ImageAdFragment : AdFragment(R.layout.fragment_image_ad) {

    private val binding by viewbind<FragmentImageAdBinding>()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        Utils.log("加载图片${model.url}")
        Glide.with(binding.ivImg.context).asBitmap().load(File(model.url)).into(binding.ivImg)
    }
}

导致第二个 fragment 的图片,展示到了第一个 fragment 里的 ImageView 上,
然后,第二个 Fragment 显示空白...

自定义View的混淆规则

作者你好,之前向你反馈的自定义View使用viewbind导致的崩溃问题,升级1.1.3版本后,已经可以正常使用。但是混淆规则却没有跟着更新,这会导致自定义View的ViewBinding类中的inflate方法被混淆掉,导致异常。所以混淆规则需要新增一个public static ** inflate(**,**);,作者可以试一试

SmartRefreshLayout自定义RefreshHeader时,报java.lang.NoSuchMethodException的错误

升级到1.1.5版本之后,SmartRefreshLayout自定义RefreshHeader时,报java.lang.NoSuchMethodException的错误:
Caused by: java.lang.NoSuchMethodException:com.xxx.xxx.databinding.LayoutCommonRefreshHeaderBinding.inflate [class android.view.LayoutInflater, class android.view.ViewGroup]
at java.lang.Class.getMethod(Class.java:2072)
at java.lang.Class.getMethod(Class.java:1693)
at com.hi.dhl.binding.ReflectExtKt.inflateMethodWithViewGroup(ReflectExt.kt:21)
at com.hi.dhl.binding.viewbind.ViewGroupViewBinding.(ViewGroupViewBinding.kt:36)
查看源码源码发现1.1.5版本viewbind扩展方法强制要求传入viewGroup引起的,自定义的RefreshHeader是通过addview方式添加进SmartRefreshLayout里面的。viewbind改回不传入viewGroup方式可正常使用,建议增加viewGroup可空的方法。

bug onGetLayoutInflater

1 androidx.fragment.app.Fragment.getLayoutInflater(Fragment.java:1503)

2 androidx.fragment.app.Fragment.onGetLayoutInflater(Fragment.java:1452)
3 androidx.fragment.app.Fragment.performGetLayoutInflater(Fragment.java:1484)
4 androidx.fragment.app.Fragment.getLayoutInflater(Fragment.java:1469)
5 com.hi.dhl.binding.viewbind.FragmentViewBinding.getValue(FragmentViewBinding.kt:34)
6 com.snmi.smclass.ui.main.SmClass5Fragment.getBinding(Unknown Source:10)
7 com.snmi.smclass.ui.main.SmClass5Fragment.access$getBinding$p(SmClass5Fragment.kt:73)
8 com.snmi.smclass.ui.main.SmClass5Fragment$loadSemesterBeans$1$2.invokeSuspend(SmClass5Fragment.kt:496)
9 kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
10 kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
11 android.os.Handler.handleCallback(Handler.java:790)
12 android.os.Handler.dispatchMessage(Handler.java:99)
13 android.os.Looper.loop(Looper.java:210)
14 android.app.ActivityThread.main(ActivityThread.java:7080)
15 java.lang.reflect.Method.invoke(Native Method)
16 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:523)
17 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:863)

反馈个bug,我用viewpager2,从kotlin-android-extensions改成这个框架报错

先是报错 FragmentManager is already executing transactions
然后我改了FragmentStateAdapter的条件
报错变成了Fragment no longer exists
但是FragmentStateAdapter saveState是final方法 和viewpager2 也是final class
所以我还原代码kotlin-android-extensions的写法就没有报错了
我应用的UI是下面三个tab,一个tab用viewpager2包两个 Fragment
在tab上切来切去就报错

Fragment生命周期监听方法不正确

当前的监听方法通过fragment.lifecycle添加了Observer,
fragment.lifecycle关联的是fragment的生命周期,而非fragment.view的生命周期,

fragment.lifecycle.addObserver { destroyed() }

由于fragment.view活跃的生命周期存在明显比fragment活跃生命周期短的情况,
(如采用Navigation库管理fragment(attach/detach))
正确的做法是采用fragment.viewLifecycleOwner.lifecycle添加Observer。

Simple one-liner ViewBinding in Fragments and Activities with Kotlin
中fragment生命周期监听的方法是正确的
(其中onDestroy回调与fragment.onDestroyView()回调对应)

fragment.lifecycle.addObserver(object : DefaultLifecycleObserver {
    override fun onCreate(owner: LifecycleOwner) {
        fragment.viewLifecycleOwnerLiveData.observe(fragment) { viewLifecycleOwner ->
            viewLifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
                override fun onDestroy(owner: LifecycleOwner) {
                    binding = null
                }
            })
        }
    }
})

PS: observers可以不额外手动remove,因为fragment.lifecycle和LiveData都在DESTROYED时做了反注册。

遇到个bug

场景: 一个activity,监听viewmodel中的livedata,两个fragment,两个fragment中都有一个按钮,点击就会通过viewmodel切换显示。 发现各自点击两次后就不能响应点击事件了

使用viewbind时,如何在使用xml布局的自定义ViewGroup中使用呢

自定义ViewGroup布局名称layout_empty_tip,根标签使用了<merge>
声明了private val binding: LayoutEmptyTipBinding by viewbind()
但是运行报错了

java.lang.NoSuchMethodException: inflate [class android.view.LayoutInflater]
at java.lang.Class.getMethod(Class.java:2068)
at java.lang.Class.getMethod(Class.java:1690)
at com.hi.dhl.binding.ReflectExtKt.inflateMethod(ReflectExt.kt:17)
at com.hi.dhl.binding.viewbind.ViewGroupViewBinding.(ViewGroupViewBinding.kt:24)

看了下应该是反射没找到inflate方法

fun Class.inflateMethod() = getMethod(INFLATE_NAME, LayoutInflater::class.java)

但是不知道怎么解决

onGetLayoutInflater() cannot be executed until the Fragment is attached to the FragmentManager

Exception java.lang.IllegalStateException: onGetLayoutInflater() cannot be executed until the Fragment is attached to the FragmentManager.
at androidx.fragment.app.Fragment.getLayoutInflater (Fragment.java:1673)
at androidx.fragment.app.Fragment.onGetLayoutInflater (Fragment.java:1622)
at androidx.fragment.app.Fragment.performGetLayoutInflater (Fragment.java:1654)
at androidx.fragment.app.Fragment.getLayoutInflater (Fragment.java:1639)
at com.hi.dhl.binding.viewbind.FragmentViewBinding.getValue (FragmentViewBinding.kt:51)
at com.aly.ticktube.ui.fragment.VideoFragment. (VideoFragment.kt:39)
at com.aly.ticktube.ui.fragment.VideoFragment.access$getMFragment (VideoFragment.kt:37)
at com.aly.ticktube.ui.fragment.VideoFragment$initView$6$1.onAnimationEnd (VideoFragment.kt:123)
at android.animation.AnimatorSet.onChildAnimatorEnded (AnimatorSet.java:829)
at android.animation.AnimatorSet.-wrap1 (AnimatorSet.java)
at android.animation.AnimatorSet$AnimatorSetListener.onAnimationEnd (AnimatorSet.java:784)
at android.animation.ValueAnimator.endAnimation (ValueAnimator.java:1153)
at android.animation.ValueAnimator.doAnimationFrame (ValueAnimator.java:1313)
at android.animation.AnimationHandler.doAnimationFrame (AnimationHandler.java:146)
at android.animation.AnimationHandler.-wrap2 (AnimationHandler.java)
at android.animation.AnimationHandler$1.doFrame (AnimationHandler.java:54)
at android.view.Choreographer$CallbackRecord.run (Choreographer.java:928)
at android.view.Choreographer.doCallbacks (Choreographer.java:705)
at android.view.Choreographer.doFrame (Choreographer.java:637)
at android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:916)
at android.os.Handler.handleCallback (Handler.java:751)
at android.os.Handler.dispatchMessage (Handler.java:95)
at android.os.Looper.loop (Looper.java:154)
at android.app.ActivityThread.main (ActivityThread.java:6816)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1565)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1453)

NoSuchMethodException问题

问题: 在继承系统布局中,如果布局文件的根是merge标签,会抛出NoSuchMethodException;替换为ConstraintLayout等则不会。调试过,貌似原因是getMethod里调用的getPublicMethodRecursive只匹配了仅有LayoutInflater类型参数的infalte方法

merge标签产生的binding类也只有一个inflate(@nonnull LayoutInflater inflater, @nonnull ViewGroup parent)这种签名的,作者有时间看看是不是这样?
备注:混淆添加了的

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.