【问题标题】:How to use livedata for making multiple network calls?如何使用 livedata 进行多个网络调用?
【发布时间】:2018-07-11 07:05:20
【问题描述】:

我正在做一个项目,我正在尝试使用数据绑定来实现 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;
} }

这是我的仓库

【问题讨论】:

  • 您得到的错误是什么? getVendorlogin 的执行是否有问题?您可以将堆栈跟踪粘贴到问题中吗?
  • 我的所有存储库功能都运行良好,但即使我在活动中观察到我的供应商 ID 实时数据也不会触发。我想观察 viewmodel 中的 vendorId 并基于此我想调用 getVendor(id)
  • vendorId = vendorRepository.login 调用之后检查 vendorId 的可空性。另外,检查OnCompleteListener 接口,看看您是否缺少任何其他回调方法。最后,在login 方法内的OnCompleteListener 中实现的所有回调方法中放置一个日志(类似于Log.d("myclass", "inside method...");。您也可以在另一个线程中保持睡眠几毫秒,每次唤醒后,检查vendorId.getValue 是否为 null
  • vendorId 不为空,我在 oncomplete 回调中获取了 id.. 但是我在 viewmodel 中的 vendorId 实时数据没有触发
  • 您将哪个观察者附加到 Livedata vendorId?我在这里看不到任何观察者。您是否已将它附加到其他课程(可能是您的活动课程)中,您显然没有在这里粘贴?还是根本没有附上?

标签: android android-architecture-components android-viewmodel android-livedata mutablelivedata


【解决方案1】:

您需要在您的activity 中的某处添加observervendorId livedata,可能在您初始化viewModel 之后在onCreate(Bundle) 中。

您的代码将如下所示。

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
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    • 2019-01-17
    • 2020-08-30
    • 1970-01-01
    • 1970-01-01
    • 2012-08-17
    • 1970-01-01
    相关资源
    最近更新 更多