AndroidUtilCode

repository·master·Indexed 12 days ago

https://github.com/blankj/androidutilcode

A powerful utility library for Android development providing encapsulated APIs for common tasks. It includes modules for activity management (ActivityUtils), network connectivity (NetworkUtils), permission handling (PermissionUtils), file I/O (FileUtils, FileIOUtils), image processing (ImageUtils), and various other system utilities like LogUtils, ToastUtils, and DeviceUtils to increase developer productivity.

Tokens
22.1K
Snippets
71
Records
125
Agent score
94%

What's inside AndroidUtilCode

  1. Overview of AndroidUtilCode modules

    master

    AndroidUtilCode is a library for Android that encapsulates commonly used functions to improve development efficiency. The project is divided into two main modules:

    1. utilcode: Contains the core utilities that are commonly used in daily Android development.
    2. subutil: Contains utility functions that are used less frequently but can help simplify tasks within the main utilcode module.

    Both modules include complete demos and unit tests to ensure reliability.

  2. Performance Comparison: BusUtils vs EventBus

    master

    BusUtils is designed as a high-performance alternative to EventBus. Performance benchmarks conducted on macOS and Android (OnePlus 6) demonstrate that BusUtils provides significant advantages in several key areas:

    • Registration/Unregistration: BusUtils is several times faster than EventBus when registering or unregistering large numbers of subscribers (e.g., 10,000 subscribers).
    • Single Subscriber Posting: When sending a high volume of events to a single subscriber, BusUtils outperforms EventBus significantly.
    • Multiple Subscriber Posting: When broadcasting to multiple subscribers, BusUtils maintains a performance lead over EventBus.

    If your project relies heavily on an event bus, switching to BusUtils can improve runtime performance and reduce code complexity.

  3. Explore AndroidUtilCode Utility Classes

    master

    The utilcode library provides a wide range of utility classes for common Android development tasks. This segment of the documentation provides direct links to the source code and demonstration activities for various utility modules.

    Key modules available include:

    • Data & Collections: ArrayUtils, CollectionUtils, MapUtils, ConvertUtils, GsonUtils.
    • Storage & Cache: CacheDiskUtils, CacheMemoryUtils, CacheDoubleUtils, FileIOUtils, FileUtils, PathUtils.
    • System & Device: DeviceUtils, NetworkUtils, PermissionUtils, BrightnessUtils, FlashlightUtils, KeyboardUtils.
    • UI & Interaction: ClickUtils, ClipboardUtils, FragmentUtils, IntentUtils, NotificationUtils, ColorUtils.
    • Media & Files: ImageUtils, EncodeUtils, EncryptUtils.
    • Logic & Debugging: LogUtils, CrashUtils, DebouncingUtils, ObjectUtils.
  4. Explore AndroidUtilCode API Reference

    master

    The utilcode library provides a comprehensive set of utility classes for Android development. You can explore the source code and implementation details for each utility via the links provided in the documentation. Many utilities also include corresponding demo activities in the feature/utilcode/pkg directory to show real-world usage.

    Key utility categories include:

    • Activity & UI: ActivityUtils, FragmentUtils, ViewUtils, ToastUtils, SnackbarUtils, KeyboardUtils, BrightnessUtils, VolumeUtils, VibrateUtils.
    • Data & Storage: SPUtils (SharedPreferences), CacheDiskUtils, CacheMemoryUtils, FileIOUtils, GsonUtils, ConvertUtils.
    • System & Device: AppUtils, DeviceUtils, PermissionUtils, NetworkUtils, RomUtils, ProcessUtils, SDCardUtils.
    • Text & Logic: StringUtils, RegexUtils, TimeUtils, NumberUtils, ArrayUtils, CollectionUtils, MapUtils.
    • Media & Graphics: ImageUtils, ColorUtils, ShadowUtils.
  5. How BusUtils works internally

    master

    BusUtils is an efficient event bus that manages event subscriptions and dispatching through several internal mechanisms:

    1. Registration

    When an object is registered via BusUtils.register(Object bus), the library:

    • Maps the object's class name to a thread-safe CopyOnWriteArraySet of subscribers in mClassName_BusesMap.
    • Processes any existing sticky events via processSticky.

    2. Event Posting

    When BusUtils.post(String tag, Object arg) is called:

    • It looks up the BusInfo associated with the tag in mTag_BusInfoMap.
    • It retrieves the cached Method instance for the subscriber's function.
    • It dispatches the event to the appropriate thread pool based on the configured threadMode.

    3. Thread Modes

    BusUtils supports multiple execution contexts via the threadMode attribute:

    • MAIN: Executes on the UI thread using Utils.runOnUiThread.
    • IO: Executes on the IO thread pool.
    • CPU: Executes on the CPU thread pool.
    • CACHED: Executes on the cached thread pool.
    • SINGLE: Executes on a single background thread pool.
    • Default: Executes on the current thread.

    4. Unregistration

    BusUtils.unregister(Object bus) removes the object from the mClassName_BusesMap to prevent memory leaks and further event dispatching to that instance.

  6. How sticky events work in BusUtils

    master

    Sticky events allow a subscriber to receive the last sent event even if it registers after the event was posted. To use this, set sticky = true in the @BusUtils.Bus annotation.

    Use BusUtils.postSticky(tag) to send a sticky event and BusUtils.removeSticky(tag) to clear it.

    public static final String TAG_NO_PARAM_STICKY  = "TagNoParamSticky";
    
    @BusUtils.Bus(tag = TAG_NO_PARAM_STICKY, sticky = true)
    public void noParamStickyFun() {/* Do something */}
    
    // Usage
    BusUtils.postSticky(TAG_NO_PARAM_STICKY);
    BusUtils.register(xxx); // Receives the sticky event immediately
    BusUtils.removeSticky(TAG_NO_PARAM_STICKY); // Removes the sticky event
    BusUtils.unregister(xxx);
  7. Implement caching with CacheDisk, CacheMemory, and CacheDouble

    master

    The library provides three levels of caching:

    1. Memory Cache (CacheMemoryUtils): Fast, volatile storage for byte arrays. Use put and get.
    2. Disk Cache (CacheDiskUtils): Persistent storage. Supports various data types like getString, getBitmap, getJsonObject, getParcelable, etc.
    3. Two-Level Cache (CacheDoubleUtils): Combines memory and disk caching for optimal performance. Provides methods to check both memory and disk counts (getCacheMemoryCount, getCacheDiskCount).

    All cache utilities support remove(key) and clear() operations.

  8. Best Practices for ApiUtils

    master

    To ensure stability and maintainability when using ApiUtils, follow these conventions:

    • Visibility: Both the api (abstract class) and the impl (implementation class) should be public. The implementation must have a public no-argument constructor.
    • API Evolution: When updating an API, treat it like the Android SDK. Add new methods to support new features rather than modifying or deleting existing ones. This prevents breaking changes for modules that haven't updated their dependencies yet.
      • Good: Adding public abstract void newMethod(Param p); to an existing abstract class.
      • Bad: Changing the signature of an existing method (e.g., adding a required parameter to an old method).
    • Organization: Place impl classes in the outermost package of the business module to make them easily discoverable for developers reviewing the module's capabilities.
  9. Advantages of using BusUtils over EventBus

    master

    BusUtils offers several developer-experience and performance benefits over traditional EventBus implementations:

    1. Flexible Parameter Support: Unlike EventBus, which requires a specific MessageEvent object to pass data (even for simple notifications), BusUtils uses unique event Tags. This allows subscriber methods to accept either zero parameters or a single parameter, making event passing more flexible.
    2. Compile-time Safety: The bus plugin generates a __bus__.json file during compilation. This file maps tags to method signatures. If a method signature is changed (e.g., adding a second parameter to a method that was previously one-parameter), the plugin will detect the mismatch at compile time, preventing runtime crashes.
    3. Reduced Code Footprint: BusUtils is highly lightweight, with a source code size of approximately 300 lines, compared to the thousands of lines typically found in EventBus implementations.
    4. Higher Performance: As demonstrated in benchmarks, BusUtils is faster in registration, unregistration, and event posting.
  10. How the ApiUtils Gradle plugin works

    master

    The api-gradle-plugin automates module-to-module communication by injecting implementation registrations into the ApiUtils.init() method during the build process.

    It uses the Gradle Transform API and ASM bytecode manipulation to:

    1. Scan: Identify all classes that extend ApiUtils.BaseApi or are annotated with @ApiUtils.Api.
    2. Map: Create a mapping between the API interface and its implementation class.
    3. Inject: Automatically insert calls to ApiUtils.registerImpl(ImplementationClass.class) inside the ApiUtils.init() method.

    This allows developers to define interfaces for inter-module communication without manually registering every implementation in the application startup code.

  11. How ApiUtils handles API implementation retrieval

    master

    The ApiUtils mechanism uses a lazy-loading, thread-safe approach to provide API implementations.

    The Workflow:

    1. Registration: During build-time, implementations are registered into an internal map (mInjectApiImplMap) where the key is the API interface (e.g., MainApi) and the value is the implementation class (e.g., MainApiImpl).
    2. Retrieval: When ApiUtils.getApi(apiClass) is called:
      • It first checks a local cache (mApiMap).
      • If not cached, it looks up the implementation class in the injected map.
      • If found, it uses newInstance() to instantiate the implementation and stores it in the cache.
    3. Requirements: Because implementations are instantiated via reflection, implementation classes must have a parameterless constructor.

    Key Benefits:

    • Lazy Initialization: Implementations are only instantiated when they are actually requested, preventing unnecessary overhead at app startup.
    • Thread Safety: Uses synchronization to ensure that multiple threads do not create duplicate instances of the same implementation.
    // Example of how the internal retrieval logic works
    public static <T extends BaseApi> T getApi(@NonNull final Class<T> apiClass) {
        return getInstance().getApiInner(apiClass);
    }
    
    // Implementation requirement: must have a parameterless constructor
    public class MainApiImpl implements MainApi {
        public MainApiImpl() { // Required
        }
    }
  12. How thread switching works in BusUtils

    master

    You can control which thread the subscriber method executes on by setting the threadMode parameter in the @BusUtils.Bus annotation. BusUtils uses ThreadUtils for thread management, providing access to various thread pools including MAIN, IO, CPU, CACHED, and SINGLE. If no mode is specified, the event is posted on the same thread that called post().

    @BusUtils.Bus(tag = "my_tag", threadMode = BusUtils.ThreadMode.MAIN)
    public void onMainThreadEvent() {
        // This will run on the Main thread
    }