Componentes de Android Jetpack (tres) ViewModel

Artículos de la serie de componentes Android Jetpack: Componente
Android Jetpack (1) Componente LifeCycle
Android Jetpack (2) Navegación
Componente Android Jetpack (3) ViewModel Componente
Android Jetpack (4) LiveData Componente
Android Jetpack (5)
Componente Room Android JetPack (6) Enlace de datos
Android Jetpack Componentes (7) Paginación de
componentes de Android Jetpack (8) WorkManager

Primer idioma

Para las aplicaciones que admiten el cambio de pantalla horizontal y vertical, cuando cambiamos entre pantallas horizontales y verticales, Activityse volverán a crear y debemos considerar el almacenamiento y la recuperación de datos. Jetpack nos proporciona componentes de ViewModel para ayudarnos a resolver este problema. ViewModel almacena y administra los datos relacionados con la interfaz de una manera orientada al ciclo de vida. ViewModel es independiente de los cambios de configuración, incluso si se Activityreconstruye, no afectará el ciclo de vida de ViewModel.
Ciclo de vida de ViewModel
En el desarrollo de aplicaciones, la lógica empresarial, como la interacción de la interfaz de usuario y la adquisición de datos, generalmente se escribe en la página. Cuando los requisitos del proyecto continúan aumentando y las funciones de la página son complejas, la clase de página aparecerá particularmente hinchada y no adecuada para el mantenimiento. Esto también viola el "principio de función única". La página solo debe ser responsable de manejar la interacción entre el usuario y los controles de la interfaz de usuario y la visualización de datos, y la lógica comercial para obtener datos debe manejarse por separado.
Android proporciona la clase ViewModel específicamente para almacenar los datos requeridos por la página de la aplicación. Puede entenderse como un puente entre la vista y el modelo de datos, que separa la vista de los datos mientras mantiene la comunicación.

ViewModel 与 onSaveInstanceState ()

Por lo general, lo usamos onSaveInstanceState()para resolver el problema de la pérdida de datos causada por la rotación de la pantalla, pero solo puede guardar una pequeña cantidad de datos que admiten la serialización, y Viewmodel admite todos los datos de la página. Cabe señalar que ViewModel no admite la persistencia de datos. Cuando la interfaz se destruye por completo, ViewModel y los datos que contiene dejarán de existir. onSaveInstanceState()Sin esta limitación, los datos de la página pueden persistir y los dos propósitos son diferente.

confiar

 	//包含了 viewmodel 和 livedata,lifecycle-extensions 中的 API 已弃用
    //implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    //或者指明使用viewmodel
    implementation "androidx.lifecycle:lifecycle-viewmodel:2.2.0"

usar

Primero, personalice un ViewModel y herede la clase ViewModel.

public class HomeViewModel extends ViewModel {
    
    

    @Override
    protected void onCleared() {
    
    
        super.onCleared();
    }
}

ViewModel es una clase abstracta y solo hay una onClear(). ActivityEste método se llamará cuando se destruya el ViewModel asociado a él. Se pueden realizar algunos trabajos relacionados con la liberación de recursos en el método. Tenga en cuenta que la Activityreconstrucción causada por la rotación de la pantalla no llamará este método.
Usamos un ejemplo de un contador para mostrar el uso de ViewModel para separar la vista de los datos.

	private int value;

    public String gtValue() {
    
    
        return String.valueOf(value);
    }

    public void addValue() {
    
    
        value+=1;
        if (onChangedListener != null) {
    
    
            onChangedListener.onChanged(String.valueOf(value));
        }
    }

    /**
     * 通过接口的形式将数据传递出去,更好的方式是通过LiveData,
     */
    public interface onChangedListener {
    
    
        void onChanged(String value);
    }

    private onChangedListener onChangedListener;

    public void setOnChangeListener(onChangedListener onChangeListener) {
    
    
        this.onChangedListener = onChangeListener;
    }

Luego Activity, cada vez que haces clic, el contador es +1, y se completa la instanciación del ViewModel ViewModelProvider. Este determinará si el ViewModel existe, si existe, regresará directamente, y si no existe, se creará. .

		HomeViewModel homeViewModel = new ViewModelProvider(this).get(HomeViewModel.class);
        textView.setText(homeViewModel.gtValue());

        button.setOnClickListener(view -> homeViewModel.addValue());
        homeViewModel.setOnChangeListener(textView::setText);

Al ejecutar el código, puede encontrar que el contador de clics será +1 y los datos no desaparecerán cuando la actividad se reconstruya girando la pantalla, lo que significa que ViewModel no se ha destruido y los datos retenidos siempre han existido.

Compartir datos entre fragmentos

ActivityDos o más a Fragmentmenudo necesitan comunicarse entre sí, este proceso es más complejo, los datos pueden ViewModel del Activitytratamiento de liberación, siempre y cuando Activityno se destruyan, ViewModel ha existido, en base a estas características, una pluralidad de los Fragmentmismos se pueden usar Activityrango compartido por ViewModel Maneja este tipo de comunicación.

 //ViewModelProvider的范围必须是所在activity
 HomeViewModel homeViewModel = new ViewModelProvider(getActivity()).get(HomeViewModel.class);

FragmentViewModel también se instancia en el otro . Al cambiar Fragment, solicitará el valor actual del contador para alcanzar la Fragmentcomunicación entre.

 homeViewModel = new ViewModelProvider(getActivity()).get(HomeViewModel.class);
 @Override
    public void onHiddenChanged(boolean hidden) {
    
    
        super.onHiddenChanged(hidden);
        Toast.makeText(getActivity(), homeViewModel.gtValue(),Toast.LENGTH_SHORT).show();
    }

En Fragmentuso ViewModel y Activitysimilar usado.

Principio de ViewModel

ViewModel recibe un ViewModelStoreOwnerobjeto como parámetro, le pasamos este, esto es por Activityherencia ComponentActivity, implementa la ViewModelStoreOwnerinterfaz por defecto . El código fuente es el siguiente.

public interface ViewModelStoreOwner {
    
    
    /**
     * Returns owned {@link ViewModelStore}
     *
     * @return a {@code ViewModelStore}
     */
    @NonNull
    ViewModelStore getViewModelStore();
}

La responsabilidad de implementar esta interfaz es mantener la propiedad durante los cambios de configuración ViewModelStorey ser llamado cuando el alcance está a punto de ser destruido.

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        LifecycleOwner,
        ViewModelStoreOwner,
        HasDefaultViewModelProviderFactory,
        SavedStateRegistryOwner,
        OnBackPressedDispatcherOwner {
    
    
        
 	public ComponentActivity() {
    
    
  		getLifecycle().addObserver(new LifecycleEventObserver() {
    
    
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
    
    
                if (event == Lifecycle.Event.ON_DESTROY) {
    
    
                    if (!isChangingConfigurations()) {
    
    
                        getViewModelStore().clear();
                    }
                }
            }
        });
 	}
 	
    @NonNull
    @Override
    public ViewModelStore getViewModelStore() {
    
    
        if (getApplication() == null) {
    
    
            throw new IllegalStateException("Your activity is not yet attached to the "
                    + "Application instance. You can't request ViewModel before onCreate call.");
        }
        if (mViewModelStore == null) {
    
    
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
    
    
                // Restore the ViewModelStore from NonConfigurationInstances
                mViewModelStore = nc.viewModelStore;
            }
            if (mViewModelStore == null) {
    
    
                mViewModelStore = new ViewModelStore();
            }
        }
        return mViewModelStore;
    }
}

getViewModelStore()El tipo devuelto es ViewModelStore. Como se puede ver en el código fuente, el ViewModel se HashMap<String,ViewModel>almacena en caché en la forma, como se mencionó anteriormente, cuando la página necesita el ViewModel, primero se determina si existe en el caché.
FragmentLa ViewModelStoreOwnerinterfaz también está implementada de forma predeterminada y el principio es Activitysimilar.
Cabe señalar que al crear una instancia del ViewModel, no pase ningún tipo Contextu Contextobjeto referenciado, lo que provocará una pérdida de memoria.

public class ViewModelStore {
    
    

    private final HashMap<String, ViewModel> mMap = new HashMap<>();

    final void put(String key, ViewModel viewModel) {
    
    
        ViewModel oldViewModel = mMap.put(key, viewModel);
        if (oldViewModel != null) {
    
    
            oldViewModel.onCleared();
        }
    }

    final ViewModel get(String key) {
    
    
        return mMap.get(key);
    }

    Set<String> keys() {
    
    
        return new HashSet<>(mMap.keySet());
    }

    /**
     *  Clears internal storage and notifies ViewModels that they are no longer used.
     */
    public final void clear() {
    
    
        for (ViewModel vm : mMap.values()) {
    
    
            vm.clear();
        }
        mMap.clear();
    }
}

AndroidViewModel

Si la instanciación de ViewModel para pasar Contextun objeto, puede usar AndroidViewModella clase que hereda de ViewModel, y recibe Applicationcomo Context, su ciclo de vida y así usar Applicationel mismo ciclo de vida, no conduce a una pérdida de memoria, mientras que el tratamiento de datos en una escena específica .

Supongo que te gusta

Origin blog.csdn.net/yang_study_first/article/details/115229934
Recomendado
Clasificación