{"id":18304227,"url":"https://github.com/smartdengg/interface-buoy","last_synced_at":"2025-04-05T15:31:13.051Z","repository":{"id":161581265,"uuid":"168485815","full_name":"SmartDengg/interface-buoy","owner":"SmartDengg","description":"ASM\u0026AOP. Safely invoke the method declared within a Java interface.","archived":false,"fork":false,"pushed_at":"2019-03-01T03:16:23.000Z","size":210,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-21T06:33:28.227Z","etag":null,"topics":["android","aop","asm","gradle","gradle-android-plugin","gradle-plugin","groovy","interface-design"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SmartDengg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-01-31T07:56:19.000Z","updated_at":"2023-09-08T17:49:53.000Z","dependencies_parsed_at":"2024-01-23T08:15:12.827Z","dependency_job_id":null,"html_url":"https://github.com/SmartDengg/interface-buoy","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SmartDengg%2Finterface-buoy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SmartDengg%2Finterface-buoy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SmartDengg%2Finterface-buoy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SmartDengg%2Finterface-buoy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SmartDengg","download_url":"https://codeload.github.com/SmartDengg/interface-buoy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247358572,"owners_count":20926249,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","aop","asm","gradle","gradle-android-plugin","gradle-plugin","groovy","interface-design"],"created_at":"2024-11-05T15:28:11.562Z","updated_at":"2025-04-05T15:31:13.037Z","avatar_url":"https://github.com/SmartDengg.png","language":"Java","readme":"# interface-buoy\n\n[![](https://jitpack.io/v/SmartDengg/interface-buoy.svg)](https://jitpack.io/#SmartDengg/interface-buoy)\n\nKotlin and groovy provide very convenient operators, the operator `?.` is only invoked when the reference object is not empty, but unfortunately, this utility operator is not provided in java.\n\nI wrote a [blog](https://www.jianshu.com/p/151023036adf) to analyze the principles of the `?.` operators in kotlin and groovy. The kotlinc and groovyc compilers compile the `?.` to the same effect as `if (callback != null) {} ` bytecode.\n\n**Interface-buoy** is an Android gradle plugin that uses ASM to dynamically modify java bytecode during the build process. Combine dynamic proxies and reflections to achieve the same effect as the '?.' effect.\n\nNote that we only modify the method defined in the java interface, that is which will trigger the [invokeinterface](https://cs.au.dk/~mis/dOvs/jvmspec/ref--32.html) instruction at runtime.\n\n\nBlog link : [在Java 中安全使用接口引用](https://www.jianshu.com/p/151023036adf)\n\n## Usage\n\n#### Command Line\n\n```bash\n$ git clone git@github.com:SmartDengg/interface-buoy.git\n$ cd interface-buoy/\n$ ./gradlew build\n```\n\n\n#### AGP\n\nAdd Android gradle plugin dependency to your any application or library module's build.gradle.\n\n\n```groovy\nbuildscript {\n    repositories {\n        maven { url 'https://jitpack.io' }\n    }\n    dependencies {\n        classpath 'com.github.SmartDengg.interface-buoy:interface-buoy-gradle:1.3.0'\n    }\n}\n\napply plugin: 'com.android.application' // or apply plugin: 'com.android.library'\napply plugin: 'com.smartdengg.interfacebuoy' // or apply plugin: 'interfacebuoy'\n\ndependencies {\n  implementation fileTree(include: ['*.jar'], dir: 'libs')\n  implementation 'com.github.SmartDengg.interface-buoy:interface-buoy-runtime:1.3.0'\n}\n\n```\n\n#### Optional\n\nIn the java code you can use `BuoySettings.loggable = true` to control whether to print the log, the default is not to print the log.\n\n\n#### Support\n\nIf the invoked interface method has a return type but not a `void` type, its bytecode will not be modified. Currently only the `void` return type is supported.\n\n- [x] void return type\n- [ ] other return type\n\n\n## Principle\n\nBefore:\n\n\n\n```\n\ninvokeinterface #3,  2            // InterfaceMethod Callback.onProgress:(I)V\n\n\n```\n\n\nAfter:\n\n\n```\n\ninvokestatic  #23                 // Method buoy$onProgress:(LCallback;I)V\n\n\nstatic void buoy$onProgress(JavaSample$Callback, int);\nCode:\n   0: aload_0\n   1: ldc           #25                 // String Callback\n   3: ldc           #27                 // String Callback.onProgress:(int)void\n   5: invokestatic  #33                 // Method com/smartdengg/interfacebuoy/compiler/InterfaceBuoy.proxy:(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;\n   8: iload_1\n   9: invokeinterface #37,  2           // InterfaceMethod Callback.onProgress:(I)V\n  14: return\n\n\n```\n\n1. Replaces `invokeinterface ` with `invokestatic` at compile time.\n\n2. Generated `Buoy$onProgress` method at compile time to prevent calling interface methods on an null object.\n\n\n## About me\n\nemail : hi4joker@gmail.com\n\nblog  : [小鄧子](https://www.jianshu.com/u/df40282480b4)\n\nweibo : [-小鄧子-](https://weibo.com/5367097592/profile?topnav=1\u0026wvr=6)\n\n\n## License\n\nSee the [LICENSE](LICENSE) file for license rights and limitations (MIT).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmartdengg%2Finterface-buoy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmartdengg%2Finterface-buoy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmartdengg%2Finterface-buoy/lists"}