Databinding oppdatering UI fra fragment ved hjelp av bindingen

stemmer
0

Tilsynelatende er det en vitenskap å databainding i android som jeg helt klart ikke får. Jeg fortsetter å havne kjemper utsikt oppdatering via fragment eller viewmodel hvor noen ting bare arbeid andre er tilsynelatende ikke-fungerende.

Jeg ønsker å deaktivere en login-knappen, endre tekst og angi en alfa etter dens blitt klikket før jeg får en API respons da jeg endre den tilbake. Ganske rett fram. Im ikke inkludert kode som vil endre den tilbake siden den stopper ved å endre den første gang.

Mens du skriver dette jeg hadde det samme problemet igjen og igjen, endrer knappen aldri. Observatøren i fragment blir kalt (I loggen viser den i den rekkefølgen jeg forventer at det skal ha blitt kalt), men brukergrensesnittet bare doesnt oppdatering. Jeg kjørte den på en emulator igjen og gjentatte ganger observatøren loggen doesnt vises før mye senere, og deretter visningen oppdatert som forventet, sorta. Det gjorde ikke oppdatere når jeg klikket på knappen, men minst knappen endret før API svaret kom tilbake. Jeg stoppet app og re-løp den og im tilbake til det opprinnelige problemet, det er ikke oppdaterer.

Im ved hjelp av SingleLiveEvent umodifisert fra googles arkitektur prøver https://github.com/android/architecture-samples/blob/dev-todo-mvvm-live/todoapp/app/src/main/java/com/example/android/architecture/ blåkopier / todoapp / SingleLiveEvent.java

activity_main_login <- det er et fragment ikke aktivitet, men jeg har ikke refactored det ennå. Dette er avkortet slik at det ikke kan fungere uten en layout container.

<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();
}

Her er hva loggene se ut når den kjører og du klikker på login knappen ...

D/MainViewModel: loginClicked()
D/MainFragment: showLoading changed
D/MainViewModel: login()
Publisert på 13/01/2020 klokken 23:52
kilden bruker
På andre språk...                            


1 svar

stemmer
0

Ikke at jeg inkluderte Retrofit2 kode som gjorde / fikk API-kall, men det hadde å gjøre med threading. Jeg pakket den metoden som kalles synkron ettermontering ressurs i

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

Så innlogging () ser mer ut som dette nå

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
        ...
    });
}

Selv om API-kall selv må gjøres på sin egen tråd (og var) hele greia bare holdt opp UI tråden mest sannsynlig på grunn av thread.join (). Som forårsaket Databindings ikke å oppdatere. Dette kan ha blitt løst ved hjelp RxJava men jeg har ikke implementert det ennå, og etter en enkel oppgave det er ikke nødvendig.

Svarte 15/01/2020 kl. 01:25
kilden bruker

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