UnPeek-LiveData Documentation

repository·master·Indexed 22 days ago

https://github.com/kunminx/unpeek-livedata

A specialized data distribution library for Android designed to solve the 'data backflow' issue in Jetpack MVVM architectures. It provides controlled, multi-observer event dispatching for the Domain Layer, preventing stale data re-injection. Key features include read/write separation via Result and MutableResult, manual memory management with the clean() method, and support for a Single Source of Truth pattern.

Tokens
1.1K
Snippets
3
Records
6
Agent score
29%

What's inside UnPeek-LiveData

  1. How UnPeek-LiveData works and when to use it

    master

    UnPeek-LiveData is a specialized data distribution tool designed for the Domain Layer to solve the "data backflow" (data re-injection) problem common with standard Jetpack LiveData.

    Key Characteristics

    • Multi-observer support: A single message can be consumed by multiple observers.
    • Controlled backflow prevention: It prevents data re-injection only after all observers have consumed the message.
    • Manual memory management: You can use the clear() method to manually remove messages from memory.
    • Read/Write Separation: Supports a "Single Source of Truth" pattern using access control (e.g., ProtectedUnPeekLiveData).

    Usage Constraints

    • Low-frequency data distribution: It is optimized for scenarios like pushing data once per second.
    • High-frequency requirements: If you need to dispatch events more frequently (e.g., 5+ times per second), use MVI-Dispatcher instead, as it uses a message queue to ensure no pushes are missed.
  2. Understand the evolution and core concepts of UnPeek-LiveData

    master

    UnPeek-LiveData is designed to solve the 'data backflow' (数据倒灌) problem in Android, where a user re-enters a screen and receives stale data from a previous session.

    Key conceptual evolutions include:

    • Data Backflow Prevention: Uses a 'delayed automatic message cleaning' design to ensure messages are distributed to all observers but are automatically cleared from memory after a certain period, preventing them from being re-delivered to new observers.
    • Result vs. Event: In version 7.6, the library moved towards a Result semantic. While Event implies a UI-triggered action (like a button click), Result signifies a message dispatched from the end of business logic (the 'single source of truth'). This encourages developers to use result.setValue only within business logic layers rather than in Activities/Fragments.
    • Read/Write Separation: Historically, ProtectedUnPeekLiveData (v2.0) provided a way to ensure only the 'trusted source' (e.g., a ViewModel) could send data, while Activities/Fragments could only observe.
    • Memory Management: Recent versions (v7.0+) use a version-tracking mechanism between proxy classes and the main LiveData class to manage observers without complex Map management, reducing memory leak risks.
  3. Install UnPeek-LiveData via Maven

    master

    To use UnPeek-LiveData in your Android project, add the following dependency to your build.gradle file. Note that the group ID has been updated from archi to arch. Additionally, ensure mavenCentral() is included in your repository configuration as JCenter is no longer supported.

    implementation 'com.kunminx.arch:unpeek-livedata:7.8.0'
  4. Create a MutableResult using the Builder pattern

    master

    You can customize the behavior of your MutableResult using its built-in Builder pattern. For example, you can specify whether null values are allowed.

    MutableResult<Moment> test =
            new MutableResult.Builder<Moment>()
            .setAllowNullValue(false)
            .create();
  5. Implement UnPeek-LiveData in a ViewModel and Fragment

    master

    To implement the "Read/Write Separation" pattern, use MutableResult within your ViewModel for writing data, and expose it as a read-only Result to your Fragment or Activity for observing. This ensures that only the ViewModel can trigger data updates.

    public class TestFragment extends Fragment {
      protected void onViewCreate(){
        viewModel.getXXXResult().observe(this, xxx ->{
          renderUI(...);
        })
    
        viewModel.requestXXX();
      }
    }
    
    public class SharedViewModel extends ViewModel {
      private final MutableResult<XXX> xxxResult = new MutableResult<>();
    
      public Result<XXX> getXXXResult(){
        return xxxResult;
      }
    
      public void requestXXX(){
        //业务逻辑 ...
        ...
        xxxResult.setValue(...);
      }
    }