Как использовать livedata для совершения нескольких сетевых вызовов?

я работаю над проектом, в котором я пытаюсь реализовать компоненты архитектуры Android с привязкой данных. У меня есть активность, модель представления и репозиторий, и я прямо сейчас создаю страницу входа. Мне нужно сделать две функции репозитория, чтобы пользователь мог войти в систему, первая функция вернет uid, и, передав этот uid, вторая функция вернет детали. как только все будет сделано, я хочу перенаправить пользователя на внутреннюю страницу. Я пробовал с Transformations.switchMap, но он не работает. Пожалуйста помоги...

public class LoginViewModel extends ViewModel {
private final VendorRepository vendorRepository;
private final ResourceProvider resourceProvider;
public MutableLiveData<String> error = new MutableLiveData<>();
public MutableLiveData<Boolean> loading = new MutableLiveData<>();
private MutableLiveData<Resource<String>> vendorId = new MutableLiveData<>();
public LiveData<Resource<Vendor>> vendor;

public LoginViewModel() {
    this.vendorRepository = VendorRepository.getInstance();
    this.resourceProvider = ResourceProvider.getInstance();
    /*vendor = Transformations.switchMap(vendorId, new Function<Resource<String>, LiveData<Resource<Vendor>>>() {
        @Override
        public LiveData<Resource<Vendor>> apply(Resource<String> input) {
            if (input!=null&&input.status.equals(Status.SUCCESS))
            return vendorRepository.getVendor(vendorId.getValue().data);
            else return null;
        }
    });*/
}

/**
 * called when a user clicks on the login button
 * if the inputs are valid, will call the login function
 *
 * @param email    entered email
 * @param password entered password
 */
public void onClickLogin(String email, String password) {
    //loading.setValue(true);
    if (validInputs(email, password)) {
        vendorId = vendorRepository.login(
                email, password
        );
    } else loading.setValue(false);
}}

Это моя модель просмотра

public class VendorRepository {
private static VendorRepository INSTANCE;
private FirebaseAuth firebaseAuth;
private FirebaseFirestore firebaseFirestore;

public static VendorRepository getInstance() {
    if (INSTANCE == null)
        INSTANCE = new VendorRepository();
    return INSTANCE;
}

private VendorRepository() {
    this.firebaseAuth = FirebaseAuth.getInstance();
    this.firebaseFirestore = FirebaseFirestore.getInstance();
}

public MutableLiveData<Resource<String>> login(String email, String password) {
    final MutableLiveData<Resource<String>> data = new MutableLiveData<>();
    data.setValue(Resource.<String>loading(null));
    firebaseAuth
            .signInWithEmailAndPassword(email, password)
            .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        data.postValue(Resource.success(task.getResult().getUser().getUid()));
                    } else {
                        data.postValue(Resource.<String>error(task.getException().getMessage(), null));
                    }
                }
            });
    return data;
}

public LiveData<Resource<Vendor>> getVendor(String id) {
    final MutableLiveData<Resource<Vendor>> data = new MutableLiveData<>();
    data.postValue(Resource.<Vendor>loading(null));
    firebaseFirestore
            .collection(DB_VENDOR)
            .document(id)
            .get()
            .addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
                @Override
                public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                    if (task.isSuccessful()) {
                        Vendor vendor = task.getResult().toObject(Vendor.class);
                        data.postValue(Resource.success(vendor));
                    } else {
                        data.postValue(Resource.<Vendor>error(task.getException().getMessage(), null));
                    }
                }
            });
    return data;
} }

это мой репозиторий


comment
Какую ошибку вы получаете? Есть ли проблема с выполнением getVendor или login? Можете ли вы вставить трассировку стека в вопрос?   -  person Rajan Prasad    schedule 11.07.2018
comment
все мои функции репозитория работают нормально, но живые данные моего идентификатора поставщика не запускаются, даже если я наблюдаю это в своей деятельности. Я хочу наблюдать за vendorId в модели представления и на основе этого я хочу вызвать getVendor(id)   -  person Vipin KT    schedule 11.07.2018
comment
Проверьте допустимость значения null для vendorId после вызова vendorId = vendorRepository.login. Кроме того, проверьте интерфейс OnCompleteListener, чтобы узнать, отсутствуют ли какие-либо другие методы обратного вызова. Наконец, поместите журнал (что-то вроде Log.d("myclass", "inside method..."); во все методы обратного вызова, которые вы реализуете в OnCompleteListener внутри метода login. Вы также можете в другом потоке продолжать спать в течение нескольких мс и после каждого пробуждения проверять, является ли vendorId.getValue null или нет .   -  person Rajan Prasad    schedule 11.07.2018
comment
vendorId не равен нулю, и я получаю идентификатор при обратном вызове oncomplete.. но мои текущие данные vendorId в модели представления не запускаются   -  person Vipin KT    schedule 11.07.2018
comment
Какого наблюдателя вы прикрепили к идентификатору вендора Livedata? Я не вижу прикрепленного сюда наблюдателя. Вы прикрепили его к какому-то другому классу (возможно, к вашему классу активности), который вы, очевидно, не вставили сюда? Или вы его вообще не прикрепили?   -  person Rajan Prasad    schedule 11.07.2018
comment
могу ли я использовать switchMap для наблюдения за vendorId и вызова getVendor() на основе изменений в vendorId   -  person Vipin KT    schedule 11.07.2018
comment
Вы можете, но вам не нужно. Вы можете вызвать VendorRepository.getInstance().getVendor( vendorId) в наблюдателе самих vendorId живых данных.   -  person Rajan Prasad    schedule 11.07.2018
comment
Я не вижу, что вам нужны оперативные данные, которые представляют собой преобразованный вывод livedata vendorId. Вероятно, вы можете втиснуть код, вызывающий вызов репозитория getVendor, в экземпляр Function<String, Livedata<Vendor>, но я не вижу в этом необходимости.   -  person Rajan Prasad    schedule 11.07.2018
comment
где я буду писать код для этого наблюдателя, я не хочу писать его в действии, как наблюдать идентификатор поставщика в модели представления   -  person Vipin KT    schedule 11.07.2018
comment
Вам нужно будет написать это в файле activity. В противном случае вам придется передавать ссылку this активности везде, где вы создаете наблюдателя. Поверьте мне, вам не нужно беспокоиться об утечке памяти, создав анонимный класс для наблюдателя в действии. В соответствии с тем, как спроектированы ViewModels, наблюдатель будет отсоединен и впоследствии уничтожен, как только действие будет уничтожено. Вы можете прочитать об этом в руководстве для разработчиков Android по ViewModels и LiveData.   -  person Rajan Prasad    schedule 11.07.2018
comment
могу ли я наблюдать MutableLiveData в действии   -  person Vipin KT    schedule 11.07.2018
comment
Да, он как бы создан для этой цели. Напишу ответ на этот вопрос.   -  person Rajan Prasad    schedule 11.07.2018
comment
спасибо за терпение, у меня все равно не работает   -  person Vipin KT    schedule 11.07.2018
comment
Проверьте ответ.   -  person Rajan Prasad    schedule 11.07.2018


Ответы (1)


Вам нужно добавить observer из vendorId живых данных где-нибудь в activity, возможно, в onCreate(Bundle) после того, как вы инициализировали viewModel.

Ваш код будет выглядеть примерно так.

public final class MyActivity extends AppCompatActivity {
    ...
    LoginViewModel mViewModel;

    @Override protected final void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_activity);
        mViewModel = ViewModelProviders.of(this)
            .get(LoginViewModel.class);

        //make vendorId public in the viewModel

        mViewModel.vendorId.observe ( this, new Observer<String> (){

            @Override public void onChanged(@Nullable final String vendorId) {
                VendorRepository.getInstance().getVendor(vendorId);
            }
        });

        //Similarly, add observer for the vendor live data
    }

}
person Rajan Prasad    schedule 11.07.2018