Databinding UI aktualizace od fragmentu s použitím vazby

hlasů
0

Zřejmě existuje věda databainding na android, které jsem jasně dont dostat. Pořád končí boj s výhledem aktualizační prostřednictvím fragmentu nebo viewmodel kde jsou zdánlivě nefunkční některé věci, které „jen“ pracovní ostatní.

Chci zakázat tlačítko pro přihlášení, změňte jeho text a nastavení alfa po jeho klikne až dostanu odpověď API pak jsem to změnit zpět. Docela rovně vpřed. Im ne včetně kódu, který se změní zpět, protože jeho zastavení na měnící se to poprvé.

Při psaní tohoto jsem měl stejný problém znovu a znovu, tlačítka se nikdy nezmění. Pozorovatel ve fragmentu volána (V protokolu se ukazuje v pořadí, očekávám, že byli povoláni), ale UI prostě doesnt aktualizace. znovu běžel jsem ho na emulátoru a opakovaně doesnt pozorovatele log objeví až mnohem později a pak toho názoru, aktualizované podle očekávání, sorta. Ono didnt aktualizovat, když jsem kliknul na tlačítko, ale alespoň tlačítko změnilo před reakci API vrátil. Zastavil jsem ji a znovu běžel ho a im zpět k původnímu problému, jeho neaktualizují.

Im pomocí SingleLiveEvent nemodifikovaná ze vzorků brýle architektury https://github.com/android/architecture-samples/blob/dev-todo-mvvm-live/todoapp/app/src/main/java/com/example/android/architecture/ plány / todoapp / SingleLiveEvent.java

activity_main_login <- jeho fragment není činnost, ale i přístav to refactored dosud. To je zkrácen, takže to nemusí fungovat bez obalu rozvržení.

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

Zde je to, co se přihlásí vypadat, když to běží, a kliknete na tlačítko pro přihlášení ...

D/MainViewModel: loginClicked()
D/MainFragment: showLoading changed
D/MainViewModel: login()
Položena 13/01/2020 v 23:52
zdroj uživatelem
V jiných jazycích...                            


1 odpovědí

hlasů
0

Ne že bych zahrnoval Retrofit2 kód, který dosažený / přijaté volání API, ale to mělo co do činění s závitem. Zabalil jsem metodu, kterou nazývá synchronní přísnějšího zdroj v

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

Takže login () vypadá spíš jako to nyní

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

I přesto, že API volání sám musí být provedeno na vlastní závitu (a bylo) celá věc jen zvedl UI vlákno s největší pravděpodobností kvůli thread.join (). To způsobilo DataBinding není aktualizace. To může být vyřešeno pomocí RxJava ale já nezavedly, že ještě i pro jednoduchý úkol to není nutné.

Odpovězeno 15/01/2020 v 01:25
zdroj uživatelem

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