DataBinding actualização UI de fragmento utilizando ligao

votos
0

Aparentemente há uma ciência para databainding no android do qual eu get claramente não faça. Eu continuo acabar lutando vistas de atualização através do fragmento ou viewmodel onde algumas coisas apenas trabalho outros são aparentemente não funcional.

Quero desativar um botão de login, altere seu texto e definir um alfa após a sua sido clicado até que eu obter uma resposta da API, então eu mudá-lo de volta. Bem direto. Im não incluindo o código que irá mudá-lo de volta desde o seu parando em mudá-lo pela primeira vez.

Enquanto escrevia este eu tive o mesmo problema repetidamente, o botão nunca muda. O observador no fragmento é chamado (No registo mostra na ordem eu espero que foram chamados), mas a interface do usuário apenas atualização não funciona. Corri-lo em um emulador novamente e repetidamente a doesnt log observador aparecer até muito mais tarde e, em seguida, a visão atualizada conforme o esperado, sorta. Aquilo não atualizar quando eu cliquei no botão mas pelo menos o botão mudou antes da resposta da API voltou. Parei o aplicativo e re-correu e volta im para a questão original, a sua não atualizar.

Im usando SingleLiveEvent não modificada a partir de amostras googles arquitetura https://github.com/android/architecture-samples/blob/dev-todo-mvvm-live/todoapp/app/src/main/java/com/example/android/architecture/ blueprints / todoapp / SingleLiveEvent.java

activity_main_login <- o seu fragmento a não atividade, mas eu não reembolsaram reformulado ainda. Esta é truncado por isso não pode funcionar sem um recipiente de layout.

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

Aqui está o que os logs olhar como quando ele é executado e você clicar no botão de login ...

D/MainViewModel: loginClicked()
D/MainFragment: showLoading changed
D/MainViewModel: login()
Publicado 13/01/2020 em 23:52
fonte usuário
Em outras línguas...                            


1 respostas

votos
0

Não que eu incluído o código Retrofit2 que fez / recebeu a chamada de API, mas que tinha a ver com o threading. Enrolei o método que chamou o recurso retrofit síncrona em

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

Então login () se parece mais com isso agora

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

Mesmo que a própria chamada de API deve ser feito em seu próprio segmento (e foi) a coisa toda simplesmente levantou o segmento interface do usuário mais provável devido à Thread.Join (). Isso fez com que os Databindings não atualização. Isso pode ter sido resolvido usando RxJava mas eu não implementaram que ainda e para uma tarefa simples que não é necessário.

Respondeu 15/01/2020 em 01:25
fonte usuário

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