java - Static methods or Singletons performance-wise (Android)?

java - Static methods or Singletons performance-wise (Android)?

Lalage Yakiv Author: Lalage Yakiv Date: 2022-10-05
java - Static methods or Singletons performance-wise (Android)?

All you need to know about java - Static methods or Singletons performance-wise (Android)? , in addintion to java - Static interface methods are only supported starting with Android N (--min-api 24): void butterknife.Unbinder.lambda$static$0() , java - Static interface methods are only supported starting with Android N (--min-api 24) , java - Why default and static interface methods are not supported by Android Studio 3.0 , java - Call non-static methods on custom Unity Android Plugins

  1. java - Static methods or Singletons performance-wise (Android)?
  2. Question:

    In an app with a small number of POJOs and lots of helper methods that operate on them, what's better performance-wise: to make the helper classes singletons or to make the methods static?


    Solution 1:

    Static methods would be very slightly better performance and memory wise:

    1. Avoid (potential) overhead of virtual function calls.
    2. Eliminates memory needed for an actual instance of the class.
    3. Eliminates need to get an instance of the class when you use it.

    But honestly I'd probably still make it a singleton anyways. The gains you'd get by not doing it are likely so small that they would make zero difference, even in a mobile environment.

    Solution 2:

    Can you avoid either situation and make them regular classes?

    Ignoring the performance question, I'd recommend avoiding singeltons and static methods to improve your testability.

    Singletons and static methods can be very hard to test; in this regard singletons are essentially static methods but with a different name. Misko Hevery, who works on the Google Test team, has a few good articles on this subject:

    • Singletons are Pathological Liars
    • Static Methods are Death to Stability

    Solution 3:

    Don't worry about absurd micro-optimizations like that. Worry about maintainability.

    It sounds like that application is written in a totally non-OO style and could benefit a lot from eliminating most of those "helper methods" and putting them where they belong, with the data they operate on.

  3. java - Static interface methods are only supported starting with Android N (--min-api 24): void butterknife.Unbinder.lambda$static$0()
  4. Question:

    I was trying to debug an app when I encountered this error

    Static interface methods are only supported starting with Android N (--min-api 24): void butterknife.Unbinder.lambda$static$0()

    Here is my gradle

    apply plugin: 'com.android.application'
    
        android {
            compileSdkVersion 29
            buildToolsVersion "29.0.3"
    
        defaultConfig {
            applicationId "com.github.webrtc"
            minSdkVersion 19
            targetSdkVersion 29
            versionCode 1
            versionName "1.0"
    
            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        }
    
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            }
            }
        }
    
    
    
    
        dependencies {
            implementation fileTree(dir: 'libs', include: ['*.jar'])
            androidTestCompile('androidx.test.espresso:espresso-core:3.1.0', {
                exclude group: 'com.android.support', module: 'support-annotations'
            })
            implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
            implementation 'fi.vtt.nubomedia:kurento-room-client-android:1.1.2' 
            implementation 'org.whispersystems:webrtc-android:M59'
            implementation 'com.jakewharton:butterknife:10.0.0'
            annotationProcessor 'com.jakewharton:butterknife-compiler:10.0.0'
            implementation "org.java-websocket:Java-WebSocket:1.3.0"
            implementation 'com.squareup.okhttp3:okhttp:3.9.0'
            implementation 'androidx.appcompat:appcompat:1.1.0'
            testImplementation 'junit:junit:4.12'
            androidTestImplementation 'androidx.test.ext:junit:1.1.1'
            androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
        }
    


    Solution 1:

    Read the "Download" section of Butterknife's github page.
    https://github.com/JakeWharton/butterknife

    android {
      ...
      // Butterknife requires Java 8.
      compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
      }
    }
    
    dependencies {
      implementation 'com.jakewharton:butterknife:10.2.1'
      annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.1'
    }
    

    You need to add the compileOptions part.

  5. java - Static interface methods are only supported starting with Android N (--min-api 24)
  6. Question:

    I do nothing, just create new project then find this error. pls help me enter image description here


    Solution 1:

    This is a common issue and you just need to add

    android {
    ...
      compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
    ...
    }
    

    There is explanation and direction in this link

  7. java - Why default and static interface methods are not supported by Android Studio 3.0
  8. Question:

    Why [Default and static interface methods] of java 8 are not supported in Android Studio 3.0?

    The code always got the error hint.

    the demo code

    The build.gradle settings :

    compileSdkVersion 26
    buildToolsVersion "26.0.2"
    defaultConfig {
        applicationId "com.dreamzone.mtime"
        minSdkVersion 18
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
    
    }
    

    But android studio doc shows it can compatible any api level. https://developer.android.com/studio/write/java8-support.html android studio doc


    Solution 1:

    You need to set Java 8 compatibility in your module's build.gradle file, via the compileOptions closure inside the android closure:

    apply plugin: 'com.android.application'
    
    android {
    
        // other good stuff here
    
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
    }
    

    Solution 2:

    // only chnage minSdkversion to more then 26

      defaultConfig {
            applicationId "com.example.myapplication"
            minSdkVersion 26
            targetSdkVersion 30
            versionCode 1
            versionName "1.0
      }
    

  9. java - Call non-static methods on custom Unity Android Plugins
  10. Question:

    I'm trying to understand how to build my own Android plugins for Android.

    I achieve to call static methods on my Java class (the one created on AndroidStudio), but I really CAN'T call non-static methods.

    I check those links:

    • https://answers.unity.com/questions/884503/cant-call-non-static-method-in-androidjavaclass.html

    • http://leoncvlt.com/blog/a-primer-on-android-plugin-development-in-unity/

    • https://answers.unity.com/questions/1327186/how-to-get-intent-data-for-unity-to-use.html

    • how to call Non-static method from Unity Android Plugin?

    But none works.

    I'm trying to get the call from a button from Unity like:

    AndroidJavaClass UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    AndroidJavaObject currentActivity = UnityPlayer.Get<AndroidJavaObject>("currentActivity");
    currentActivity.Call("SayHi");
    

    And my activity on Android looks like:

    public class MainActivity extends UnityPlayerActivity {
        private static final String TAG = "LibraryTest";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d(TAG, "Created!");
        }
    
        public void SayHi()
        {
            Log.d(TAG, "HI_");
        }
    }
    

    My ADB is throwing this message: enter image description here

    I've also tried calling instead of UnityPlayer call it like:

    AndroidJavaClass pluginClass = new AndroidJavaClass("com.example.eric.librarytest.MainActivity");
    

    EDIT: This is my AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.eric.librarytest"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk
            android:minSdkVersion="24"
            android:targetSdkVersion="28" />
    
        <application android:label="@string/app_name" >
            <activity
                android:name="com.example.eric.librarytest.MainActivity"
                android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    

    But doesn't work either for non-static methods, it works only for static methods if I do pluginClass.CallStatic(""), any idea?

    EDIT 2:

    • Taras Leskiv suggest to change UnityPlayer.Get to UnityPlayer.GetStatic, but then i get the follow error:

      error: java.lang.NoSuchMethodError: no non-static method with name='SayHi' signature='()V' in class Ljava.lang.Object;

    • Proguard is not active.


    Solution 1:

    When you are doing this:

    AndroidJavaClass UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    AndroidJavaObject currentActivity = UnityPlayer.Get<AndroidJavaObject>("currentActivity");
    currentActivity.Call("SayHi");
    

    It doesn't work because the currentActivity field is static, what you should do is:

    AndroidJavaClass UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    AndroidJavaObject currentActivity = UnityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
    currentActivity.Call("SayHi");
    

    Notice the UnityPlayer.GetStatic part

    Here is other convenience snippet from one of my plugins:

        static AndroidJavaObject _activity;
    
        public static AndroidJavaObject Activity
        {
            get
            {
                if (_activity == null)
                {
                    var unityPlayer = new AndroidJavaClass(C.ComUnity3DPlayerUnityPlayer);
                    _activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
                }
                return _activity;
            }
        }
    

    Solution 2:

    Maybe it has to do with java inheritence : your currentActivity AndroidJavaObject is of class com.unity3d.player.UnityPlayer but this class does not have SayHi method, you should cast your object to MainActivity before calling your method.

    Solution 3:

    My code was correct, the problem was the Project structure.

    My Project was like:

    Assets
    ├── Plugins
    │   ├── classes.jar
    

    And should be like:

    Assets
    ├── Plugins
    │   ├── Android
    │   │   ├── classes.jar
    

    Was obvius (not for me) cause the error spam the message that could not find the signature, so the software can't read those classes.