Enlace de datos de actualización de interfaz de usuario de fragmento utilizando la unión

votos
0

Al parecer hay una ciencia a databainding en Android de la que se beneficiaron claramente no haga. Sigo luchando para terminar vistas de actualización a través del fragmento o modelo de vista en algunas cosas que otros sólo trabajo son aparentemente no funcional.

Quiero desactivar un botón de inicio de sesión, cambiar su texto y establecer un alfa después de su hecho click hasta que consiga una respuesta del API luego cambiarlo de nuevo. Muy claro. Im no incluyendo el código que va a cambiar de nuevo desde su parada en el cambio de la primera vez.

Mientras que escribir esto, tenía el mismo problema una y otra vez, el botón no cambia nunca. El observador en el fragmento se llama a (En el registro se muestra en el orden que espero que han sido llamados), pero la interfaz de usuario acaba de actualización no funciona. Yo corría en un emulador de nuevo y repetidamente el imposible de registro observador aparece hasta mucho más tarde y luego la visión actualizada como se esperaba, sorta. Nos dio actualiza cuando hice clic en el botón, pero al menos el botón cambiado antes de que la respuesta de la API de regresar. Dejé de la aplicación y re-encontré con él y volver im al tema original, su falta de actualización.

Im usando SingleLiveEvent no modificada a partir de muestras de arquitectura gafas https://github.com/android/architecture-samples/blob/dev-todo-mvvm-live/todoapp/app/src/main/java/com/example/android/architecture/ planos / todoapp / SingleLiveEvent.java

activity_main_login <- es un fragmento no la actividad pero que no he refactorizan todavía. Esto se trunca por lo que podría no funcionar sin un contenedor de diseño.

<layout
    xmlns:android=http://schemas.android.com/apk/res/android
    xmlns:app=http://schemas.android.com/apk/res-auto
    xmlns:tools=http://schemas.android.com/tools>

    <data>
        <variable
            name=mainViewModel
            type=com.example.viewmodel.MainViewModel />
    </data>
    ...
    <Button
        android:id=@+id/btnLogin
        android:layout_width=135dp
        android:layout_height=47dp
        android:layout_marginLeft=8dp
        android:layout_marginRight=8dp
        android:layout_marginTop=16dp
        android:onClick=@{() -> mainViewModel.loginClicked()}
        android:text=@string/login
        android:textColor=#ffffff
        android:textStyle=bold
        android:background=#e05206
        app:layout_constraintLeft_toLeftOf=parent
        app:layout_constraintRight_toRightOf=parent
        app:layout_constraintTop_toBottomOf=@+id/fingerprintSwitch
        tools:layout_editor_absoluteX=101dp />
    ....
</layout>

MainFragment

ActivityMainLoginBinding binding;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    Log.d(TAG, -> onCreateView() );
    super.onCreateView(inflater, container, savedInstanceState);

    mainViewModel = new ViewModelProvider(this).get(MainViewModel.class);

    getLifecycle().addObserver(mainViewModel);

    binding = DataBindingUtil.inflate(inflater, R.layout.activity_main_login, container, false);
    mView = binding.getRoot();
    binding.setMainViewModel(mainViewModel);
    binding.setLifecycleOwner(this); // Yeah this is what I forgot last time...

    return mView;
}

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    AppLog.d(TAG, -> onViewCreated() );
    super.onViewCreated(view, savedInstanceState);

    mainViewModel.getShowLoading().observe(getViewLifecycleOwner(), showLoading -> {
        AppLog.d(TAG, showLoading changed);
        this.loading = true;

        binding.btnLogin.setText(R.string.loggingIn);
        binding.btnLogin.setEnabled(false);
        binding.btnLogin.setAlpha(.5f);
    });
}

MainViewModel

private SingleLiveEvent<Boolean> showLoading = new SingleLiveEvent<>();

public void loginClicked() {
    Log.d(TAG, loginClicked());
    showLoading.setValue(true);
    login();
}

Esto es lo que los registros se ven como cuando se ejecuta y hace clic en el botón de inicio de sesión ...

D/MainViewModel: loginClicked()
D/MainFragment: showLoading changed
D/MainViewModel: login()
Publicado el 13/01/2020 a las 23:52
fuente por usuario
En otros idiomas...                            


1 respuestas

votos
0

No es que he incluido el código Retrofit2 que hizo / recibido la llamada a la API pero tenía que ver con la rosca. Envolví el método que llama el recurso de adaptación sincronizada en

new Handler().post(() -> { });

Así login () se parece más a esto ahora

private void login() {
    new Handler().post(() -> {
        // original retrofit call
        Thread t = new Thread(() -> authResponse = restApi.doAuthSync());
        t.start();

        // Joining thread so we wait for the response
        // I believe this to be the actual culprit of the problem
        try {
            t.join();
        } catch (InterruptedException e) {
            Log.e(TAG, e.getMessage());
        }

        // handle authResponse
        ...
    });
}

A pesar de que la propia llamada a la API se debe realizar en su propio hilo (y fue) toda la cosa acaba de celebrar el hilo de interfaz de usuario muy probablemente debido a la Thread.Join (). Eso hizo que los Databindings no actualización. Esto puede haber sido resuelto mediante RxJava pero no han aplicado todavía y que para una tarea sencilla que no es necesario.

Respondida el 15/01/2020 a las 01:25
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more