【问题标题】:Android MVVM retrofit2 model not updatingAndroid MVVM retrofit2 模型未更新
【发布时间】:2019-07-26 00:12:07
【问题描述】:

尝试使用改造调用我的 API 并更新模型。它正确初始化并且能够提取数据,但是当我通过按下更新按钮手动触发它时,onChange QuestionResponse 模型为空。这似乎是一种竞争条件,因为在调试时它会在调用 onResponse 之前触发 onChange。我尝试从 setValue 更改为 postvalue 等。

活动

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mViewModel = ViewModelProviders.of(this).get(BasicViewModel.class);
    mViewModel.getQuestions().observe(this, new Observer<QuestionResponse>() {
        @Override
        public void onChanged(QuestionResponse response) {
            QuestionResponse temp = mViewModel.getQuestions().getValue();
            Toast.makeText(MainActivity.this, "Questions Updated", Toast.LENGTH_SHORT).show();
        }
    });

    updateButton = findViewById(R.id.updateButton);
    updateButton .setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            update();
        }
    });
}

private void update(){
    mViewModel.updateQuestions();
}

查看模型

private Repository repository;
private Application application;
private MutableLiveData<QuestionResponse> questionMutableLiveData;

public BasicViewModel(Application application){
    super(application);
    this.application = application;
    repository = new Repository();
    questionMutableLiveData = repository.getQuotes();
}

public void updateQuestions(){
    questionMutableLiveData.setValue(repository.getQuotes().getValue());
}

public LiveData<QuestionResponse> getQuestions(){
    if(questionMutableLiveData == null){
        System.out.println("Something Is Wrong");
    }
    return questionMutableLiveData;
}

改装服务

public class Repository {
    MutableLiveData<QuestionResponse> questionData;
    ApiService apiService;

    public QuoteMRepository(){
        apiService = RetrofitSingleton.getRetrofitInstance().create(ApiService.class);
    }

    public MutableLiveData<QuestionResponse> getQuotes(){
        Call<QuestionResponse> call = apiService.getQuestions();

        //Old version of doing it 
        //MutableLiveData<QuestionResponse> questionData = new MutableLiveData<>();

        //New version, seems to be working but triggering twice 
        if(questionData == null) {
            questionData = new MutableLiveData<>();
        }    

        call.enqueue(new Callback<QuestionResponse>() {
            @Override
            public void onResponse(Call<QuestionResponse> call, Response<QuestionResponse> response) {
                if(response.isSuccessful()){
                    QuestionResponse reply = response.body();
                    questionData.setValue(reply);
                }
            }

            @Override
            public void onFailure(Call<QuestionResponse> call, Throwable t) {
                System.out.println("Failure");
            }
        });

        return questionData;
    }
}

【问题讨论】:

    标签: android retrofit2 android-mvvm


    【解决方案1】:

    您将返回一个空的 LiveData 对象,然后使用存储库响应对其进行更新,因此您的观察者会触发两次,一次用于 null,一次用于响应。

    public MutableLiveData<QuestionResponse> getQuotes(){
        Call<QuestionResponse> call = apiService.getQuestions();
        MutableLiveData<QuestionResponse> questionData = new MutableLiveData<>();
    
        call.enqueue(new Callback<QuestionResponse>() {
            @Override
            public void onResponse(Call<QuestionResponse> call, Response<QuestionResponse> response) {
                if(response.isSuccessful()){
                    QuestionResponse reply = response.body();
                    questionData.setValue(reply);
                }
            }
    
            @Override
            public void onFailure(Call<QuestionResponse> call, Throwable t) {
                System.out.println("Failure");
            }
        });
    
        // THIS RETURNS AN EMPTY OBJECT AND LATER UPDATES
        return questionData;
    }
    

    例如,您可以在观察者上按null 过滤,或者为您的LiveData 使用SwitchMap 并返回一个指示加载的包装器。

    【讨论】:

    • 为什么在创建 ViewModel 并且仅在调用 updateQuestions 时不会发生?我看过一些例子,我认为他们没有在观察者中使用任何类型的过滤。以medium.com/@amtechnovation/… 为例。一个简单的解决方案是将我的 api 调用移动到我的视图模型中,但这有点打破了模式。
    • 因为你的值最初是null,所以再次赋值null并不会触发observer。
    • 嗯,我不确定我完全理解你的意思,但你的评论给了我一个想法。正如您所说,我的主要活动也不是在听,每次我都会返回一个新的可变 LiveData。我编辑了我的问题的代码以显示存储库中的更改。它似乎有效,但可能仍会触发两次。
    • 您更新的代码不应触发两次。您还可以在声明时初始化 LiveData 对象。
    • 它肯定触发了两次,但是通过改变 questionMutableLiveData.setValue(repository.getQuotes().getValue());只是 repository.getQuotes().getValue() 似乎修复它
    【解决方案2】:

    相信我解决了这个问题。第一个问题是我总是在我的存储库中创建并返回一个新的可变列表。这个新列表没有被观察到,但仍然被分配了一个值。 onChange observable 在主要活动中仍然被触发的原因是因为在 ViewModel questionMutableLiveData.setValue(repository.getQuotes().getValue()) 实际上正在更改数据,但新创建的可变列表的值为空。

    如果有任何反馈,如果这是正确的或组织存储库/视图模型的更好方法,我很乐意听到!

    活动

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        mViewModel = ViewModelProviders.of(this).get(BasicViewModel.class);
        mViewModel.getQuestions().observe(this, new Observer<QuestionResponse>() {
            @Override
            public void onChanged(QuestionResponse response) {
                QuestionResponse temp = mViewModel.getQuestions().getValue();
                Toast.makeText(MainActivity.this, "Questions Updated", Toast.LENGTH_SHORT).show();
            }
        });
    
        updateButton = findViewById(R.id.updateButton);
        updateButton .setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                update();
            }
        });
    }
    
    private void update(){
        mViewModel.updateQuestions();
    }
    

    查看模型

    private Repository repository;
    private Application application;
    private MutableLiveData<QuestionResponse> questionMutableLiveData;
    
    public BasicViewModel(Application application){
        super(application);
        this.application = application;
        repository = new Repository();
        questionMutableLiveData = repository.getQuotes();
    }
    
    public void updateQuestions(){
        repository.getQuotes().getValue();
    }
    
    public LiveData<QuestionResponse> getQuestions(){
        if(questionMutableLiveData == null){
            System.out.println("Something Is Wrong");
        }
        return questionMutableLiveData;
    }
    

    改装服务

    public class Repository {
        MutableLiveData<QuestionResponse> questionData;
        ApiService apiService;
    
        public QuoteMRepository(){
            apiService = RetrofitSingleton.getRetrofitInstance().create(ApiService.class);
        }
    
        public MutableLiveData<QuestionResponse> getQuotes(){
            Call<QuestionResponse> call = apiService.getQuestions();
    
            if(questionData == null) {
                questionData = new MutableLiveData<>();
            }    
    
            call.enqueue(new Callback<QuestionResponse>() {
                @Override
                public void onResponse(Call<QuestionResponse> call, Response<QuestionResponse> response) {
                    if(response.isSuccessful()){
                        QuestionResponse reply = response.body();
                        questionData.setValue(reply);
                    }
                }
    
                @Override
                public void onFailure(Call<QuestionResponse> call, Throwable t) {
                    System.out.println("Failure");
                }
            });
    
            return questionData;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-30
      • 2017-05-15
      • 2020-01-17
      • 1970-01-01
      • 2018-10-29
      • 1970-01-01
      • 2015-06-14
      • 2014-08-04
      相关资源
      最近更新 更多