directory

  • What are assertions and when should you use androidAssert?

  • 2. Remove assertion code from release and keep it only in debug

  • 3. Integrate AndroidAssert library

  • conclusion

What are assertions and when should you use androidAssert?

Assertions are usually used to verify the results returned by a function during unit testing. Used in automated tests to verify program performance.

But instead of using assertions in unit tests, we’ll talk about using assertions in project business code.

Let’s look at a couple of examples that you’re all very familiar with. Using assertions in these cases makes the code more elegant and robust.

Example 1, writeFile

/** * We want to call writeFile() only on child threads. Calls to writeFile() on main threads may cause UI lag or ANR. * * If writeFile() is called on the main thread, we print a log to warn the developer */
public void writeFile(a) {
    // The main thread prints logs to warn developers
    if(! ThreadTypeUtil.isSubThread()){ Log.e(TG,"you should call writeFile at sub thread");
    }
    // write file ...
}
Copy the code

When a developer tries to call the writeFile() method on the main thread, we log to warn the developer. However, log notifications are weak and often ignored by developers.

So we improved the code:

public void writeFile(a) {
    // Debug: the main thread calls writeFile and throws an exception to interrupt the program
    if(! ThreadTypeUtil.isSubThread()){if(BuildConfig.DEBUG) {
            throw new RuntimeException("you should call writeFile at sub thread"); }}// write file ...
}
Copy the code

When a programmer attempts to call writeFile() on the main thread, in debug mode we throw an exception and crash the program. To interrupt his development. Force him to optimize the code.

We introduced the assertion library and continued to transform the code to make it cleaner and prettier:

/** * In debug mode, AssertionFailedError will be raised directly. Let the developer * execute writeFile() normally in release mode without throwing an exception. * /
public void writeFile(a) {
    AndroidAssert.assertSubThread();
    // write file ...
    Log.i(TG, "writeFile...");
}
Copy the code

AndroidAssert. AssertSubThread () assertions for the child thread mean, judge whether the current thread must be the child thread, if not, then the exception is thrown an AssertionFailedError is generated.

AndroidAssert is an open source library that you need to introduce before using, as I’ll cover later.

Continue to optimize

Only in the Debug version, the AndroidAssert class is useful;

On the release version of APK, can I remove AndroidAssert calls?

So let’s dig a hole, finish the example, and then release the method that deletes the code. Just bear with me, everybody.

Example 2, updateUI

/** * In the release version, if we call updateUI in the child thread, we return directly without doing UI updates. * In debug, however, if updateUI is called in a child thread, an exception is raised directly and the developer can find the exception call and resolve it. * /
public void updateUI(a) {
    boolean isMainThread = ThreadTypeUtil.isMainThread();
    if(! isMainThread) { AndroidAssert.fail("updateUI must be called at main thread");
        return;
    }
    //update ui ....
    Log.i(TG, "updateUI...");
}
Copy the code

Example 3, startMainActivity

/** * asserts that the context is non-empty. If it is null, debug mode raises an exception AssertionFailedError */
public void startMainActivity(Context context) {
    AndroidAssert.assertNotNull("context must not null", context);
    if (context == null) {
        return;
    }
    //startMainActivity...
    Log.i(TG, "startMainActivity...");
}
Copy the code

Example 1: Remove the assertion code from the release version and keep it only in debug

Only in the Debug version, the AndroidAssert class is useful;

On the release version of APK, can I remove AndroidAssert calls?

Or when packing, remove all AndroidAssert calls and AndroidAssert classes, and then pack.

Which brings me to ProGuard.

Add the following configuration to ProGuard:

Dontoptimize is configured in proGuard. Will lead to proguard don't do code optimization, will not delete AndroidAssert class - assumenosideeffects class com. It. Uncle. Lib. Util. AndroidAssert {public *; }Copy the code

Can’t open the assumenosideeffects dontoptimize

The usage of doubt can, look at this article blog:blog.csdn.net/jiese1990/a…

And official wiki:www.guardsquare.com/en/products…

Summation Enoside effects are valid

  1. Decompile debug and release packages.

For example, TestActivity in our demo

public class TestActivity extends MainActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); AndroidAssert.assertNotNull(getIntent()); }}Copy the code

We decompress the debug and Release packages, respectively, to find the TestActivity code comparison:

  1. After the success of the configuration, packaged in mapping search: com. It. Uncle. Lib. Util. AndroidAssert

Proguard Not configured – assumenosideEffects mapping. TXT file

The mapping.txt file of -assumenosideEffects is configured for proGuard.

3. Integrate AndroidAssert library

  • gradle

    implementation 'com. Ituncle: android - assert: hundreds'
    Copy the code
  • Initialize the SDK and call it as soon as possible. It is recommended to call it at Application#onCreate.

// Whether to throw an exception when the initialization of ---- assertion fails
AndroidAssert.enableThrowError(BuildConfig.DEBUG);// We set it to debug mode to throw exceptions only when assertions fail
Copy the code
  • Add ProGuard and remove AndroidAssert’s code when starting a confused version

    Dontoptimize is configured in proGuard. Will lead to proguard don't do code optimization, will not delete AndroidAssert class - assumenosideeffects class com. It. Uncle. Lib. Util. AndroidAssert {public *; }Copy the code




conclusion

Android-assert is a very simple, lightweight Library of Android assertions. An Assert class similar to Junit.

Android-assert is not for writing test cases; you can use it directly in project code.

In Debug mode, an assertion failure raises an assertion exception AssertionFailedError. In Release mode, no exception is raised.

More about android – assert, see lot documentation: https://github.com/AITUncle/AndroidAssert