【问题标题】:Android MVP architecture - communication between repository and viewAndroid MVP 架构 - 存储库和视图之间的通信
【发布时间】:2017-05-12 19:38:16
【问题描述】:

我正在学习给定here 的 Android MVP 架构。根据示例,我创建了自己的简单应用程序,该应用程序仅显示带有 recyclerview 的列表,并具有拉取刷新功能。

当列表被拉出时,我想首先清除 recyclerview,然后从存储库中重新加载数据(假延迟延迟)。但是,当我清除 RecyclerViewAdpater 中的数据时,存储库中的所有数据也都被清除了,没有什么可显示的。我只是无法理解原因。

这是我创建 Presenter 和 View(即 Fragment)的活动:

    protected void onCreate(Bundle savedInstanceState) {

            mainFragment = MainFragment.newInstance();

            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.add(R.id.contentFrame, mainFragment);
            transaction.commit();

            new MainPresenter(new MainDataRepository(), mainFragment);
    }

这是我的 Fragment (MainFragment) - 注意: updateList(null) - 这是它清除所有数据的地方,包括 Repository 内部的数据:

    public MainFragment() {
    }

    public static MainFragment newInstance() {
        return new MainFragment();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //....

        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                recyclerAdapter.updateList(null); // **This is where it clears all data, including inside Repository**

                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mPresenter.loadList(); // to reload the list
                    }
                }, 1500);
            }
        });

        //...
    }

    @Override
    public void onResume() {
        super.onResume();

        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mPresenter.loadList();
            }
        }, 3000);
    }

    @Override
    public void setPresenter(MainContractor.Presenter presenter) {
        mPresenter = presenter;
    }

    @Override
    public void showList(List<String> mainDataList) {
        if(recyclerAdapter == null) {
            recyclerAdapter = new RecyclerAdapter(mainDataList);
            recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
            recyclerView.setAdapter(recyclerAdapter);
        }else{
            recyclerAdapter.updateList(mainDataList);
        }
    }

这是我的演示者 (MainPresenter):

    public MainPresenter(MainDataRepository mainDataRepository, MainContractor.View view){
        mMainDataRepository = mainDataRepository;
        mMainContractorView = view;

        view.setPresenter(this);
    }

    @Override
    public void loadList() {
        ArrayList<String> strings = mMainDataRepository.getList();

        mMainContractorView.showList(strings);
    }

这是我的存储库(MainDataRepository):

private ArrayList<String> repositoryList;

    public MainDataRepository() {
        createList();
    }

    private void createList() {
        if(repositoryList == null){
            repositoryList = new ArrayList<>();
        }

        for (int i = 1; i <= 10; i++) {
            repositoryList.add("Item " + i);
        }
    }

    public ArrayList<String> getList(){
        return repositoryList;
    }

最后一个,这就是我在 RecyclerAdapter 中更新 recyclerview 的方式:

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {

    private List<String> stringsList;

    public RecyclerAdapter(List<String> stringsList) {
        this.stringsList = stringsList;
    }

    public void updateList(List<String> newStrings){
            if(newStrings != null){
                stringsList = newStrings;
            }else{
                stringsList.clear();
            }
            notifyDataSetChanged();
        }

       //....
}

为什么 RecyclerAdapter 中的 updateList 方法也会清除存储库中 ArrayList&lt;String&gt; repositoryList 的数据?

【问题讨论】:

标签: android design-patterns mvp


【解决方案1】:

这是因为你引用了同一个对象。 在这里,您从存储库返回列表,更好的选择是返回其副本:

public ArrayList<String> getList(){
    return new ArrayList<>(repositoryList);
}

那么它将是另一个带有复制项目的对象。

【讨论】:

  • 您的调整让它正常工作!但我认为这个mMainContractorView.showList(strings); 会通过值而不是引用传递strings 对象。 Java 在这个场景中不是按值传递吗?
  • @Umarov 它是按值传递的,您传递一个列表,然后将其分配给其他引用,然后清除它,但它仍然是同一个列表。 pass-by-reference 意味着如果你给你过去的引用赋值,它将覆盖传入引用中的值,而 pass-by-value 意味着新的引用将保存你的对象,并且在给它赋值之后,你会只是失去对前一个对象的引用。你可以在相关问题中阅读更多,有很多解释
  • 阅读了this 的答案,我现在明白了按值传递的真正含义。感谢您的宝贵时间!
猜你喜欢
  • 2020-03-16
  • 1970-01-01
  • 1970-01-01
  • 2011-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-23
相关资源
最近更新 更多