ViewModelProvider.NewInstanceFactory - 接收相同的实例

时间:2018-02-08 22:21:13

标签: android mvvm android-livedata

我想重新使用ViewModel和LiveData来从Firebase读取节点。这是我在Fragment中的代码

        FirebaseDatabaseViewModel test = ViewModelProviders.of(this, new FirebaseDatabaseViewModel.Factory(getActivity().getApplication(),"node1")).get(FirebaseDatabaseViewModel.class);
    LiveData<DataSnapshot> ldTest = test.getDataSnapshotLiveData();
    ldTest.observe(this, new Observer<DataSnapshot>() {
        @Override
        public void onChanged(@Nullable DataSnapshot dataSnapshot) {
            Log.d("MyTag", "liveData.observe TEST dataSnapshot = " + dataSnapshot);
        }
    });

    FirebaseDatabaseViewModel test2 = ViewModelProviders.of(this, new FirebaseDatabaseViewModel.Factory(getActivity().getApplication(),"node2")).get(FirebaseDatabaseViewModel.class);
    LiveData<DataSnapshot> ldTest2 = test2.getDataSnapshotLiveData();
    ldTest2.observe(this, new Observer<DataSnapshot>() {
        @Override
        public void onChanged(@Nullable DataSnapshot dataSnapshot) {
            Log.d("MyTag", "liveData.observe TEST2 dataSnapshot = " + dataSnapshot);
        }
    });
}

这是ViewModel

public class FirebaseDatabaseViewModel extends AndroidViewModel {

private final String mRef;
private final FirebaseQueryLiveData liveData;

public FirebaseDatabaseViewModel(Application application, String ref) {
    super(application);
    this.mRef = ref;
    this.liveData = new FirebaseQueryLiveData(FirebaseDatabase.getInstance().getReference(mRef));
}

@NonNull
public LiveData<DataSnapshot> getDataSnapshotLiveData() {
    return liveData;
}

public static class Factory extends ViewModelProvider.NewInstanceFactory {

    @NonNull
    private final Application mApplication;

    private final String mRef;

    public Factory(@NonNull Application application, String ref) {
        mApplication = application;
        this.mRef = ref;
    }

    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
        return (T) new FirebaseDatabaseViewModel(mApplication, mRef);
    }
}

}

这是LiveData

public class FirebaseQueryLiveData extends LiveData<DataSnapshot> {

private final Query query;
private final MyValueEventListener listener = new MyValueEventListener();

public FirebaseQueryLiveData(Query query) {
    this.query = query;
}

public FirebaseQueryLiveData(DatabaseReference ref) {
    this.query = ref;
}

@Override
protected void onActive() {
    Log.d("MyTag", "onActive");
    query.addValueEventListener(listener);
}

@Override
protected void onInactive() {
    Log.d("MyTag", "onInactive");
    query.removeEventListener(listener);
}

private class MyValueEventListener implements ValueEventListener{

    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        setValue(dataSnapshot);
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        Log.e("MyTag", "Can't listen to query " + query, databaseError.toException());
    }
}

}

问题是从FirebaseDatabase读取相同的节点

D / MyTag:liveData.observe TEST dataSnapshot = DataSnapshot {key = node1,value = {.....

D / MyTag:liveData.observe TEST2 dataSnapshot = DataSnapshot {key = node1,value = {....

第二次我期望node2

1 个答案:

答案 0 :(得分:1)

默认ViewModelProvider仅为给定的类名保留一个ViewModel。我们Factory被调用的唯一时间是,当时尚未存在ViewModel - 在您的情况下,您为这两个来电使用相同的类名,因此您的第二个工厂是从未使用过。

通常,您应该考虑只使用一个ViewModel,并根据传入的密钥返回多个不同的LiveData实例,并保留HashMap<String,LiveData>以避免重新创建{{1}它已经拥有的对象:

LiveData