【问题标题】:Not getting my data correctly using ViewModelProviders?没有使用 ViewModelProviders 正确获取我的数据?
【发布时间】:2020-04-11 13:45:17
【问题描述】:

我正在尝试使用 MVVM,我正在尝试获取 Viewodel 中的数据(通常来自服务)并将它们设置为我的活动,但是当我尝试一个简单的 ArrayList 时,它似乎不起作用的 ContractModel 并将其添加到我的适配器中,一切正常,但是当我尝试调用我的 ViewModel 时,一切都停止了。

我正在学习的课程与我做的事情相同,但结果却不同。

这是我的 MainActivity:

public class MainActivity extends AppCompatActivity {

    ContractsListViewModel contractsListViewModel;

    @BindView(R.id.contractList)
    RecyclerView contractList;

    RecyclerView.Adapter adapter;

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

        ButterKnife.bind(this);

        contractList.setLayoutManager(new LinearLayoutManager(this));

        contractsListViewModel = ViewModelProviders.of(this).get(ContractsListViewModel.class);
        contractsListViewModel.call();

        adapter = new ContractListAdapter(this, contractsListViewModel.contractList.getValue());

        contractList.setAdapter(adapter);

    }
}

那是我的 ViewModel :

public class ContractsListViewModel extends ViewModel {
   public MutableLiveData<List<ContractModel>> contractList;
   MutableLiveData<Boolean> isLoading;
   MutableLiveData<Boolean> error;

   public void call(){
    fetchContracts();
   }

   public void fetchContracts(){

    ContractModel contractModel = new ContractModel(1, "hfdfd", "h");
    ContractModel contractModel1 = new ContractModel(1, "hfdffddd", "h");
    ContractModel contractModel2 = new ContractModel(1, "hdffd", "j");
    ContractModel contractModel3 = new ContractModel(1, "hdffdfd", "h");

    List<ContractModel> list = new ArrayList<ContractModel>();

    list.add(...allofthem);

    contractList.setValue(list);

  }
}

我的适配器工作正常,因为它与我上面提到的 ArrayList 一起工作。 但这里是:

public class ContractListAdapter extends RecyclerView.Adapter<ContractListAdapter.ContractViewHolder> {

    List<ContractModel> contracts;
    Context context;
    public ContractListAdapter(Context context, List<ContractModel> contracts){
        this.context = context;
        this.contracts = contracts;
    }

    @NonNull
    @Override
    public ContractViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.contrat, parent, false);
        return new ContractViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ContractViewHolder holder, int position) {
        holder.bind(contracts.get(position));
    }

    @Override
    public int getItemCount() {
        return this.contracts.size();
    }

    public class ContractViewHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.courtier)
        TextView courtier;

        public ContractViewHolder(@NonNull View view){
            super(view);
            ButterKnife.bind(this, view);
        }

        public void bind(ContractModel contractModel){
            courtier.setText(contractModel.getCourtier());
        }

    }
}

任何帮助将不胜感激。

【问题讨论】:

    标签: java android viewmodel android-adapter


    【解决方案1】:

    快速修复

    public MutableLiveData<List<ContractModel>> contractList=new MutableLiveData<>();
    

    因为你应该先创建一个列表,然后再在这里设置数据contractList.setValue(list);

    更结构化的解决方案

    public class ContractsListViewModel extends ViewModel {
    public MutableLiveData<List<ContractModel>> contractList=new MutableLiveData<>();
    MutableLiveData<Boolean> isLoading;
    MutableLiveData<Boolean> error;
    
    public void call(){
        fetchContracts();
    }
    
    public void fetchContracts(){
    
        ContractModel contractModel = new ContractModel(1, "hfdfd", "h");
        ContractModel contractModel1 = new ContractModel(1, "hfdffddd", "h");
        ContractModel contractModel2 = new ContractModel(1, "hdffd", "j");
        ContractModel contractModel3 = new ContractModel(1, "hdffdfd", "h");
    
        List<ContractModel> list = new ArrayList<ContractModel>();
    
        list.add(contractModel);
        list.add(contractModel1);
        list.add(contractModel2);
        list.add(contractModel3);
    
    
        contractList.postValue(list);
    
     }
    }
    

    MainActivity onCreate()

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        ButterKnife.bind(this);
    
        contractList.setLayoutManager(new LinearLayoutManager(this));
    
        contractsListViewModel =  ViewModelProviders.of(this).get(ContractsListViewModel.class);
        contractsListViewModel.call();
        contractsListViewModel.contractList.observe(this,contractModels -> {
             adapter = new ContractListAdapter(MainActivity.this, contractModels);
             contractList.setAdapter(adapter);
        });
    
     }
    

    查看this 了解 setValue 和 postValue 之间的区别

    【讨论】:

      【解决方案2】:

      我认为您的代码中的问题是列表的引用在响应到达并传递给适配器时一次又一次地改变,虽然您还没有发布适配器的代码,但我可以假设您正在覆盖列表引用在适配器中,你应该做什么从启动开始在适配器中保留一个 ArrayList,当你将新列表传递给适配器时,在现有列表中添加项目并调用 notifyDataSetChanged(),因此适配器将对列表有旧的引用和将刷新回收站视图中的新项目。 表示代码

      Class MyAdapter extends RecycelerviewAdapter{
      
      private List<ContractModel> globalList = new ArrayList();
      
      public ( List<ContractModel> newlist){
      globalList.addAll(newlist)
      }
      
      public updateList(List<ContractModel> newlist){
      globalList.addAll(newlist)
      }
      

      }

      我还注意到一件事,你没有观察到 livedata 的变化,所以很明显,下次当你获取合约时,你不会得到任何触发点,什么时候用 notifyDataSetChanged 刷新你的适配器。

      所以在你的活动中写下这样的东西。我正在编写伪代码以供理解。

      contractsListViewModel.contractList.observe{
      adapter.updateList(newList);
      adapter.notifydataSetCHanged()
      }
      

      【讨论】:

      • 您现在可以检查一下我的适配器吗?
      • 是的,你是对的,我会考虑到这一点
      猜你喜欢
      • 1970-01-01
      • 2019-01-22
      • 1970-01-01
      • 1970-01-01
      • 2015-08-16
      • 2020-06-21
      • 2014-11-15
      • 2017-01-02
      • 1970-01-01
      相关资源
      最近更新 更多