-
Notifications
You must be signed in to change notification settings - Fork 48
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
Can't use TabLayout.IOnTabSelectedListener2 #590
Comments
The shortened version the Java code that is being compiled is: interface GenericIface<T extends Runnable> {
public void m (T value);
}
interface ExtendedRunnable extends Runnable {
}
interface SpecificIface extends GenericIface<ExtendedRunnable> {
}
class NonGenericExtends implements SpecificIface, GenericIface {
public void m (ExtendedRunnable value) {
}
} though in the app's specific case it's: public class MainActivity
extends androidx.appcompat.app.AppCompatActivity
implements
mono.android.IGCUserPeer,
com.google.android.material.tabs.TabLayout.OnTabSelectedListener,
com.google.android.material.tabs.TabLayout.BaseOnTabSelectedListener
{ The problem here is that We will need to update the Java Callable Wrapper generator to only emit (Related: why is the Java Callable Wrapper generator emitting both interface types in the first place, when the C# code is |
A possible workaround is to bypass this bug in the Java Callable Wrapper generator by binding a new Java class which has the appropriate inheritance hierarchy: package jcw_kludge;
public class MainAppCompatActivity extends androidx.appcompat.app.AppCompatActivity
implements com.google.android.material.tabs.TabLayout.OnTabSelectedListener
{
public void onTabSelected(com.google.android.material.tabs.TabLayout.Tab tab) {}
public void onTabUnselected(com.google.android.material.tabs.TabLayout.Tab tab) {}
public void onTabReselected(com.google.android.material.tabs.TabLayout.Tab tab) {}
} Compile public class MainActivity : JcwKludge.MainAppCompatActivity {
// ...
} This should in turn result in a Java Callable Wrapper for |
Possible Workaround number 2 -- only sketched out here -- doesn't require an intermediate Step 1: Add a Step 2: Contents of package jcw_kludge;
public class MainAppCompatActivity extends androidx.appcompat.app.AppCompatActivity
implements com.google.android.material.tabs.TabLayout.OnTabSelectedListener
{
public void onTabSelected(com.google.android.material.tabs.TabLayout.Tab tab) {}
public void onTabUnselected(com.google.android.material.tabs.TabLayout.Tab tab) {}
public void onTabReselected(com.google.android.material.tabs.TabLayout.Tab tab) {}
} Then in C#-land, "hand-bind" this type [Register ("jcw_kludge. MainAppCompatActivity", DoNotGenerateAcw=true)]
public class AppCompatActivityKludge : AppCompatActivity, TabLayout.IOnTabSelectedListener2 {
[Register ("onTabReselected", "()V", "")]
public virtual void OnTabReselected(TabLayout.Tab tab)
{
throw new NotImplementedException();
}
public virtual void OnTabSelected(TabLayout.Tab tab)
{
throw new NotImplementedException();
}
public virtual void OnTabUnselected(TabLayout.Tab tab)
{
throw new NotImplementedException();
}
} Then the C# Note: This solution is incomplete. In order to fully work, Binding the |
The bug is here: The problem is that we iterate over all C# interfaces implemented by the type (e.g. The fix is to filter out interfaces "already implemented" by another interface found in the iteration. |
binding a new Java class which has the appropriate inheritance hierarchy Addedd class TabLayoutAppCompatActivity dotnet/java-interop#590
Context: dotnet/java-interop#590 Without the Java.Interop bump, fails with: obj/Debug/android/src/crc64eadbb4d7d7a577cd/JI590.java(4,8): javac error JAVAC0000: error: JI590 is not abstract and does not override abstract method invoke(MyRunnable) in InvokeRunnable [/Volumes/Xamarin-Work/xamarin-android/tests/CodeGen-Binding/Xamarin.Android.JcwGen-Tests/Xamarin.Android.JcwGen-Tests.csproj] obj/Debug/android/src/crc64eadbb4d7d7a577cd/JI590.java(4,8): javac error JAVAC0000: public class JI590 [/Volumes/Xamarin-Work/xamarin-android/tests/CodeGen-Binding/Xamarin.Android.JcwGen-Tests/Xamarin.Android.JcwGen-Tests.csproj] obj/Debug/android/src/crc64eadbb4d7d7a577cd/JI590.java(4,8): javac error JAVAC0000: [/Volumes/Xamarin-Work/xamarin-android/tests/CodeGen-Binding/Xamarin.Android.JcwGen-Tests/Xamarin.Android.JcwGen-Tests.csproj] obj/Debug/android/src/crc64eadbb4d7d7a577cd/JI590.java(29,14): javac error JAVAC0000: error: name clash: invoke(Runnable) in JI590 and invoke(MyRunnable) in InvokeRunnable have the same erasure, yet neither overrides the other [/Volumes/Xamarin-Work/xamarin-android/tests/CodeGen-Binding/Xamarin.Android.JcwGen-Tests/Xamarin.Android.JcwGen-Tests.csproj] obj/Debug/android/src/crc64eadbb4d7d7a577cd/JI590.java(29,14): javac error JAVAC0000: public void invoke (java.lang.Runnable p0) [/Volumes/Xamarin-Work/xamarin-android/tests/CodeGen-Binding/Xamarin.Android.JcwGen-Tests/Xamarin.Android.JcwGen-Tests.csproj] obj/Debug/android/src/crc64eadbb4d7d7a577cd/JI590.java(29,14): javac error JAVAC0000: [/Volumes/Xamarin-Work/xamarin-android/tests/CodeGen-Binding/Xamarin.Android.JcwGen-Tests/Xamarin.Android.JcwGen-Tests.csproj]
That's not the only issue in play. Fix it, and we get:
in which public class JI590
extends java.lang.Object
implements
mono.android.IGCUserPeer,
com.xamarin.android.InvokeMyRunnable
{
/* … */
public void invoke (java.lang.Runnable p0)
{
n_invoke (p0);
}
} Yes, now we only have the "most derived" interface type listed, but we also need to emit an |
Background: this is the Java code to bind: package com.xamarin.android;
public interface InvokeRunnable<T extends Runnable> {
void invoke (T runnable);
}
public final class MyRunnable implements Runnable {
public void run() {
}
}
public interface InvokeMyRunnable extends InvokeRunnable<MyRunnable> {
} This is the C# code we want to be able to write: class JI590 : Java.Lang.Object, IInvokeMyRunnable {
// though see https://github.com/xamarin/java.interop/issues/669
public void Invoke (Java.Lang.Object p0)
{
}
} How do we fix things so that
|
It's never this easy! Given:
What should we generate for the
|
For that specific example, I don't think it matters: If we remove The [global::Java.Interop.JavaTypeParameters (new string [] {"T extends java.lang.Runnable"})] This brings us to what I believe is your actual question: what do we do about constructed types? The original example had The answer will be glib, but: we should choose a representation which makes the Java Callable Wrapper update as simple and understandable as possible. That could mean emitting: partial class GenericMethodClass {
public unsafe void NestedGeneric (
[global::Java.Interop.JavaTypeParameter ("java.lang.Iterable<T>")]Java.Lang.IIterable p0) { ... }
} (as we usually use Java or JNI names in these attributes, not C# names), or we may want to break it into pieces: namespace Java.Interop
[AttributeUsage (AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue)]
public sealed class JavaConstructedTypeAttribute : Attribute {
public JavaConstructedTypeAttribute (string jniTypeName, string[] jniTypeParameters, string[] jniTypeArguments);
}
} allowing: partial class GenericMethodClass {
public unsafe void NestedGeneric (
[global::Java.Interop. JavaConstructedType ("java/lang/Iterable", new[]{"T"}, new []{"java/lang/Object"})]
Java.Lang.IIterable p0) { ... }
} My only concern with this is it might make for "custom attribute bloat" and increase the size of the |
Hi, I tried to create a Java class as mentioned in Workaround #2. The Java class and my custom TabLayoutMediator are defined in a Xamarin.Android library because I need to access it from different Xamarin.Android apps. Am I missing something? |
The workaround did not work for me either. At the moment I cannot get an event when the user re-selects the currently selected tab. Having tried for a few hours, I'm going to suggest my team waits for this issue to be resolved. |
Having same issue. |
Is there anything happening with this issue? Still exists. |
Any update here? |
There is no update on this issue. The easiest workaround is to continue to use |
@jpobst Archiving android app with target API 29 will fail since IOnTabSelectedListener is obsolete. |
I'm not sure I understand why it would fail? Using an obsolete API should just be a warning, not an error? |
It should, but it blocks the archiving process |
Do you have some form of treating warnings as errors turned on for your |
Good point, I rest my case. |
Xamarin.Android Version (eg: 6.0):
Tried with 9.0 and 10.0
Operating System & Version (eg: Mac OSX 10.11):
Mac OSX 10.15.3
Support Libraries Version (eg: 23.3.0):
Android X only
Describe your Issue:
If you implement the following interface
TabLayout.IOnTabSelectedListener2
You'll get the following exception
I first noticed this error when updating to Google.Android.Material 1.1.0-rc2 because on that version
TabLayout.IOnTabSelectedListener
is marked obsolete so I implemented TabLayout.IOnTabSelectedListener2But this same exception happens on 1.0.0-preview02
Steps to Reproduce (with link to sample solution if possible):
AxTabError.zip
The text was updated successfully, but these errors were encountered: