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

Я работаю над проектом, в котором пытаюсь реализовать компоненты архитектуры 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;
} }

Это мое репо

Какую ошибку вы получаете? Есть проблема в исполнении getVendor или login? Можете ли вы вставить трассировку стека в вопрос?

Rajan Prasad 11.07.2018 09:34

все мои функции репозитория работают нормально, но данные моего идентификатора поставщика в реальном времени не запускаются, даже если я наблюдаю это в своей деятельности. Я хочу наблюдать за vendorId в модели просмотра и на основании этого хочу вызвать getVendor (id)

Vipin KT 11.07.2018 09:39

Проверьте наличие значения NULL для vendorId после вызова vendorId = vendorRepository.login. Кроме того, проверьте интерфейс OnCompleteListener, чтобы увидеть, не пропущены ли вам какие-либо другие методы обратного вызова. Наконец, поместите журнал (что-то вроде Log.d("myclass", "inside method..."); во все методы обратного вызова, которые вы реализуете в OnCompleteListener внутри метода login. Вы также можете в другом потоке продолжать спать в течение нескольких мс и после каждого пробуждения проверять, является ли vendorId.getValuenull или нет .

Rajan Prasad 11.07.2018 09:52

vendorId не равен нулю, и я получаю идентификатор в обратном вызове oncomplete .. но мои данные vendorId в реальном времени в viewmodel не запускаются

Vipin KT 11.07.2018 09:58

Какого наблюдателя вы прикрепили к идентификатору поставщика Livedata? Я не вижу прикрепленных сюда наблюдателей. Вы прикрепили его к какому-либо другому классу (вероятно, к вашему классу деятельности), который вы, очевидно, не вставляли здесь? Или вы его совсем не прикрепили?

Rajan Prasad 11.07.2018 10:04

Могу ли я использовать switchMap для наблюдения за vendorId и вызвать getVendor () на основе изменений в vendorId

Vipin KT 11.07.2018 10:09

Можно, но не обязательно. Вы можете вызвать VendorRepository.getInstance().getVendor( vendorId) в самом обозревателе живых данных vendorId.

Rajan Prasad 11.07.2018 10:13

Я не вижу, что вам нужны живые данные, которые представляют собой преобразованный вывод данных vendorId Live. Вы, вероятно, можете вставить код, вызывающий вызов репозитория getVendor, в экземпляр Function<String, Livedata<Vendor>, но я не вижу в этом необходимости.

Rajan Prasad 11.07.2018 10:15

где я напишу код для этого наблюдателя, я не хочу писать его в действии, как наблюдать идентификатор поставщика в модели просмотра

Vipin KT 11.07.2018 10:16

Вам как бы придется записать его в activity. В противном случае вам придется передавать ссылку this на действие, где бы вы ни создавали наблюдателя. Поверьте, вам не нужно беспокоиться об утечке памяти, создав анонимный класс для наблюдателя в действии. Как разработаны модели ViewModels, наблюдатель будет отсоединен и впоследствии уничтожен, как только активность будет уничтожена. Вы можете прочитать об этом в руководстве для разработчиков Android на ViewModels и LiveData.

Rajan Prasad 11.07.2018 10:18

могу ли я наблюдать за MutableLiveData в действии

Vipin KT 11.07.2018 10:23

Да, он вроде как создан для этой цели. Напишу ответ на этот вопрос.

Rajan Prasad 11.07.2018 10:24

спасибо за терпение, в любом случае это не работает для меня

Vipin KT 11.07.2018 10:28

Проверьте ответ.

Rajan Prasad 11.07.2018 10:36
2
14
935
1

Ответы 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
    }

}

Другие вопросы по теме