Git Product home page Git Product logo

hoc081098 / viewbindingdelegate Goto Github PK

View Code? Open in Web Editor NEW
114.0 3.0 15.0 4.9 MB

Simple one-liner ViewBinding in Fragments and Activities with Kotlin 🍄 Simplify usage of Android View Binding with Kotlin Property Delegates and solve behavior of Fragment’s ViewLifecycleOwner 🌱 ViewBindingPropertyDelegate

Home Page: https://jitpack.io/#hoc081098/ViewBindingDelegate

License: MIT License

Kotlin 100.00%
viewbinding viewbindingdelegate android-viewbing view-binding view-binding-delegate viewbinding-delegate androidviewbinding android-viewbinding-delegate android-view-binding-delegate viewbinding-property-delegate

viewbindingdelegate's Introduction

ViewBindingDelegate

  • Simplify usage of Android View Binding with Kotlin Property Delegates and solve behavior of Fragment’s ViewLifecycleOwner.
  • Simple one-liner ViewBinding in Fragments and Activities with Kotlin.
  • Lightweight and simple library.

Month Week Android Tests Android build CI Jitpack GitHub ktlint Kotlin API Hits

Liked some of my work? Buy me a coffee (or more likely a beer)

"Buy Me A Coffee"

Medium article

Read ViewBinding Delegate — one line to get details about implementation.

Getting Started

1. Add the JitPack repository to your build file

Add it in your root build.gradle at the end of repositories:

  • Kotlin
allprojects {
  repositories {
    ...
    maven(url = "https://jitpack.io")
  }
}
  • Groovy
allprojects {
  repositories {
    ...
    maven { url 'https://jitpack.io' }
  }
}

2. Add the dependency

dependencies {
  implementation("com.github.hoc081098:ViewBindingDelegate:1.4.0")
}

3. Enable ViewBinding

https://developer.android.com/topic/libraries/view-binding#setup

Usage

import com.hoc081098.viewbindingdelegate.*

1. Activity (with reflection). See example

Click to expand
class MainActivity : AppCompatActivity(R.layout.activity_main) {
  private val viewBinding by viewBinding<ActivityMainBinding>()

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    viewBinding.button.setOnClickListener {
      startActivity(Intent(this@MainActivity, SecondActivity::class.java))
    }
  }
}

2. Activity (without reflection): Pass ::bind method reference. See example

Click to expand
class SecondActivity : AppCompatActivity(R.layout.activity_second) {
  private val binding by viewBinding(ActivitySecondBinding::bind)

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding.root
  }
}

3. Fragment (with reflection). See example

Click to expand
class FirstFragment : Fragment(R.layout.fragment_first) {
  private val binding by viewBinding<FragmentFirstBinding> {
    button.setOnClickListener(null)
  }

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    binding.button.setOnClickListener {
      findNavController().navigate(R.id.actionFirstFragmentToSecondFragment)
    }
  }
}

4. Fragment (without reflection): Pass ::bind method reference. See example

Click to expand
class SecondFragment : Fragment(R.layout.fragment_second) {
  private val binding by viewBinding(FragmentSecondBinding::bind)

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    binding.root
  }
}

5. Includes <merge/> tag layout: Create 2 ViewBinding property. See example

Click to expand
class ThirdFragment : Fragment(R.layout.fragment_third) {
  private val includeBinding by viewBinding<FragmentThirdIncludeBinding>()
  private val binding by viewBinding<FragmentThirdBinding> { buttonThird.setOnClickListener(null) }

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    includeBinding.textViewThirdInclude.text = "Working..."
    binding.buttonThird.setOnClickListener {
      Toast.makeText(requireContext(), "Clicked", Toast.LENGTH_SHORT).show()
    }
  }
}

6. The Dialog of DialogFragmentSee example

Extends DefaultViewBindingDialogFragment or implements ViewBindingDialogFragment.

Click to expand
class DemoDialogFragment : DefaultViewBindingDialogFragment() {
  private val viewBinding by dialogFragmentViewBinding(R.id.root, DialogFragmentDemoBinding::bind)
  private val viewBinding2 by dialogFragmentViewBinding<DialogFragmentDemoBinding>(R.id.root)

  override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return AlertDialog.Builder(requireContext())
      .setTitle("Demo dialog")
      .setNegativeButton("Cancel") { _, _ -> }
      .setPositiveButton("OK") { _, _ -> }
      .setView(R.layout.dialog_fragment_demo)
      .create()
  }

  override fun onResume() {
    super.onResume()

    viewBinding.textInputLayout
    viewBinding2.textInputLayout
  }
}

7. inflateViewBinding extension methods on ViewGroup/LayoutInflater/Context. See example

Can be used in RecyclerView.Adapter # onCreateViewHolder to easily create a RecyclerView.ViewHolder with a ViewBinding.

Click to expand
import com.hoc081098.viewbindingdelegate.inflateViewBinding

class DemoAdapter : ListAdapter<String, DemoAdapter.VH>(...) {
  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = VH(parent inflateViewBinding false)

  override fun onBindViewHolder(holder: VH, position: Int) = holder.bind(getItem(position))

  class VH(private val binding: ItemRecyclerBinding) : RecyclerView.ViewHolder(binding.root) {
    fun bind(item: String) { ... }
  }
}

Note

1. Activity

Must setContentView before access ViewBinding property. This can be done easily with constructor:

public AppCompatActivity(@LayoutRes int contentLayoutId) { ... }
class MainActivity : AppCompatActivity(R.layout.activity_main) { ... }

2. Fragment

Fragment's View must be not null before access ViewBinding property. This can be done easily with constructor:

public Fragment(@LayoutRes int contentLayoutId) { ... }
class FirstFragment : Fragment(R.layout.fragment_first) { ... }

3. Proguard

If there is any problem with Proguard, add below to your app/proguard-rules.pro:

# ViewBindingDelegate uses Reflection.
-keepclassmembers class ** implements androidx.viewbinding.ViewBinding {
    public static ** bind(android.view.View);

    public static ** inflate(android.view.LayoutInflater, android.view.ViewGroup, boolean);

    public static ** inflate(android.view.LayoutInflater, android.view.ViewGroup);
}

4. Throws IllegalStateException: "Attempt to get view binding when fragment view is destroyed" when accessing delegate property in onDestroyView

Since version 1.0.0-alpha03 - Feb 16, 2021, we cannot access ViewBinding delegate property in onDestroyView (this causes many problems). Recommended way is passing a lambda to onDestroyView: (T.() -> Unit)? = null parameter of extension functions, eg.

- private val binding by viewBinding<FragmentFirstBinding>()

+ private val binding by viewBinding<FragmentFirstBinding> { /*this: FragmentFirstBinding*/
+   button.setOnClickListener(null)
+   recyclerView.adapter = null
+ }

  override fun onDestroyView() {
    super.onDestroyView()
-   binding.button.setOnClickListener(null)
-   binding.recyclerView.adapter = null
  }

5. Min SDK version

Since version 1.2.0, minSdkVersion has been changed to 14.

License

MIT License

Copyright (c) 2020-2022 Petrus Nguyễn Thái Học

viewbindingdelegate's People

Contributors

hoc081098 avatar renovate-bot avatar renovate[bot] avatar s-h-y-a 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

viewbindingdelegate's Issues

IllegalStateException Can't access the Fragment View's LifecycleOwner

In multiple fragments, we are facing the same issue.

Fatal Exception: java.lang.IllegalStateException: Can't access the Fragment View's LifecycleOwner for c0{7609394} (cc0421c4-bee5-4696-b899-4d95ab41c37b id=0x7f0a01d8) when getView() is null i.e., before onCreateView() or after onDestroyView()

we are declaring and initialising the binding as follows

private val binding by viewBinding(FragmentXBinding::bind)

Any hint or help would be highly appreciated

PS: we are using latest version 1.4.0

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • Update dependency org.jetbrains.kotlin:kotlin-gradle-plugin to v1.9.25
  • Update dependency androidx.appcompat:appcompat to v1.7.0
  • Update dependency androidx.test.ext:junit to v1.2.1
  • Update dependency androidx.test.ext:junit-ktx to v1.2.1
  • Update dependency androidx.test:runner to v1.6.2
  • Update dependency com.android.tools.build:gradle to v7.4.2
  • Update dependency com.autonomousapps.dependency-analysis:com.autonomousapps.dependency-analysis.gradle.plugin to v1.33.0
  • Update dependency com.squareup.leakcanary:leakcanary-android to v2.14
  • Update dependency gradle to v7.6.4
  • Update dependency org.jetbrains.kotlinx:binary-compatibility-validator to v0.16.3
  • Update dependency org.jmailen.gradle:kotlinter-gradle to v3.16.0
  • Update lifecycle_version to v2.8.5 (androidx.lifecycle:lifecycle-viewmodel-ktx, androidx.lifecycle:lifecycle-common, androidx.lifecycle:lifecycle-livedata-core-ktx, androidx.lifecycle:lifecycle-common-java8)
  • Update actions/cache action to v4
  • Update actions/checkout action to v4
  • Update actions/setup-java action to v4
  • Update actions/upload-artifact action to v4
  • Update dependency androidx.databinding:viewbinding to v8
  • Update dependency com.android.tools.build:gradle to v8
  • Update dependency com.autonomousapps.dependency-analysis:com.autonomousapps.dependency-analysis.gradle.plugin to v2
  • Update dependency gradle to v8
  • Update dependency org.jetbrains.kotlin:kotlin-gradle-plugin to v2
  • Update dependency org.jmailen.gradle:kotlinter-gradle to v4
  • 🔐 Create all rate-limited PRs at once 🔐

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/build.yml
  • actions/checkout v3
  • actions/setup-java v3
  • actions/cache v3
  • actions/upload-artifact v3
  • actions/upload-artifact v3
  • actions/upload-artifact v3
.github/workflows/remove-old-artifacts.yml
  • c-hive/gha-remove-artifacts v1
.github/workflows/test.yml
  • actions/checkout v3
  • actions/setup-java v3
  • actions/cache v3
  • reactivecircus/android-emulator-runner v2
  • actions/checkout v3
  • actions/setup-java v3
  • actions/cache v3
  • actions/checkout v3
  • actions/setup-java v3
  • actions/cache v3
gradle
gradle.properties
ktlint.gradle
settings.gradle
build.gradle
  • com.android.tools.build:gradle 7.3.1
  • org.jetbrains.kotlin:kotlin-gradle-plugin 1.9.21
  • org.jmailen.gradle:kotlinter-gradle 3.12.0
  • org.jetbrains.kotlinx:binary-compatibility-validator 0.13.2
  • com.autonomousapps.dependency-analysis:com.autonomousapps.dependency-analysis.gradle.plugin 1.13.1
app/build.gradle
  • androidx.appcompat:appcompat 1.6.1
  • androidx.fragment:fragment-ktx 1.5.3
  • androidx.fragment:fragment 1.5.3
  • androidx.constraintlayout:constraintlayout 2.1.4
  • com.google.android.material:material 1.6.1
  • androidx.recyclerview:recyclerview 1.2.1
  • androidx.customview:customview 1.1.0
  • androidx.lifecycle:lifecycle-livedata-core-ktx 2.5.1
  • androidx.lifecycle:lifecycle-common 2.5.1
  • androidx.lifecycle:lifecycle-viewmodel-ktx 2.5.1
  • androidx.navigation:navigation-common 2.5.2
  • androidx.navigation:navigation-fragment-ktx 2.5.2
  • androidx.navigation:navigation-fragment 2.5.2
  • androidx.navigation:navigation-ui-ktx 2.5.2
  • androidx.navigation:navigation-ui 2.5.2
  • androidx.navigation:navigation-runtime-ktx 2.5.2
  • androidx.navigation:navigation-runtime 2.5.2
  • androidx.test.ext:junit 1.1.5
  • androidx.test.espresso:espresso-core 3.4.0
  • com.squareup.leakcanary:leakcanary-android 2.9.1
library/build.gradle
  • androidx.fragment:fragment-ktx 1.5.3
  • androidx.lifecycle:lifecycle-livedata-core-ktx 2.5.1
  • androidx.lifecycle:lifecycle-common-java8 2.5.1
  • androidx.lifecycle:lifecycle-common 2.5.1
  • androidx.databinding:viewbinding 7.4.2
  • androidx.collection:collection 1.2.0
  • androidx.test:core-ktx 1.4.0
  • androidx.test.ext:junit-ktx 1.1.5
  • androidx.test:runner 1.4.0
  • androidx.test:core 1.4.0
  • androidx.fragment:fragment-testing 1.5.3
  • androidx.appcompat:appcompat 1.6.1
gradle-wrapper
gradle/wrapper/gradle-wrapper.properties
  • gradle 7.5.1

  • Check this box to trigger a request for Renovate to run again on this repository

Get Crashes Can't access the Fragment View's LifecycleOwner when getView()

Get crashes like this even when i already check if lifecycle at least in STARTED

Fatal Exception: java.lang.IllegalStateException: Can't access the Fragment View's LifecycleOwner when getView() is null i.e., before onCreateView() or after onDestroyView()
at androidx.fragment.app.Fragment.getViewLifecycleOwner(Fragment.java:361)
at android.view.View.performClick(View.java:7297)
at android.view.View.performClickInternal(View.java:7274)
at android.view.View.access$3600(View.java:819)
at android.view.View$PerformClick.run(View.java:28023)
at android.os.Handler.handleCallback(Handler.java:914)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:225)
at android.app.ActivityThread.main(ActivityThread.java:7564)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

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.