使用 MasterDetail Flow 中的新数据更新 RecyclerView

Update RecyclerView with new data in MasterDetail Flow

我正在为平板电脑开发一个移动应用程序,我使用 Android Studio 步骤添加了一个 Master/Detail 流程。我在 Master Detail 上方有一组 4 个按钮 select a "Product" 然后,当你点击其中一个时,RecyclerView 会更新数据。

我的问题是,如果您点击一个按钮(产品),然后点击另一个按钮,再点击另一个按钮,等等。所有数据都一起加载,所以我需要弄清楚如何 update/refresh RecyclerView。

在我的 RecyclerViewAdapter 中,我添加了一个方法来清除、更新 ITEMS,然后通知 DataSetChanged。这适用于其余按钮,但不适用于默认情况下以编程方式单击的第一个按钮。第一个按钮再次设置 RecyclerView。

ProductListActivity

public class ProductListActivity extends AppCompatActivity implements View.OnClickListener {

    /**
     * Whether or not the activity is in two-pane mode, i.e. running on a tablet
     * device.
     */
    private boolean mTwoPane;

    // Group of buttons
    private Button[] btn = new Button[4];
    private Button btn_unfocus;
    private int[] btn_id = {R.id.btn0, R.id.btn1, R.id.btn2, R.id.btn3};

    private View recyclerView;
    private ItemRecyclerViewAdapter mAdapter;
    private MyDatabase mMyDatabase;

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

        if (findViewById(R.id.product_detail_container) != null) {
            // The detail container view will be present only in the
            // large-screen layouts (res/values-w900dp).
            // If this view is present, then the
            // activity should be in two-pane mode.
            mTwoPane = true;
        }

        mMyDatabase = Utils.getDatabase(ProductListActivity.this);

        recyclerView = findViewById(R.id.product_list);
        assert recyclerView != null;

        // Initialize the button group
        initButtonGroup();
    }

    private void initButtonGroup() {
        for(int i = 0; i < btn.length; i++){
            btn[i] = (Button) findViewById(btn_id[i]);
            btn[i].setBackgroundColor(ContextCompat.getColor(this, R.color.customGreenDark));
            btn[i].setTextColor(Color.WHITE);
            btn[i].setOnClickListener(this);
        }

        btn_unfocus = btn[0];

        // Set the first button clicked by default
        btn[0].performClick();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn0 :
                setFocus(btn_unfocus, btn[0]);
                List<Presentation.IdAndPresentationTuple> presentationList1 = mMyDatabase.presentationDao()
                        .getProductRepresentationsByName("Product 1");
                // Set up for the first time
                setupRecyclerView((RecyclerView) recyclerView, presentationList1);
                mAdapter.updateData(presentationList1);
                break;

            case R.id.btn1:
                setFocus(btn_unfocus, btn[1]);
                List<Presentation.IdAndPresentationTuple> presentationList2 = mMyDatabase.presentationDao()
                        .getProductRepresentationsByName("Product 2");
                // Update data
                mAdapter.updateData(presentationList2);
                break;

            case R.id.btn2:
                setFocus(btn_unfocus, btn[2]);
                List<Presentation.IdAndPresentationTuple> presentationList3 = mMyDatabase.presentationDao()
                        .getProductRepresentationsByName("Product 3");
                // Update data
                mAdapter.updateData(presentationList3);
                break;
        }
    }

    private void setFocus(Button btn_unfocus, Button btn_focus){
        btn_unfocus.setTextColor(Color.WHITE);
        btn_unfocus.setTypeface(null, Typeface.NORMAL);
        btn_unfocus.setBackgroundColor(ContextCompat.getColor(this, R.color.customGreenDark));
        btn_focus.setTextColor(Color.BLACK);
        btn_focus.setTypeface(null, Typeface.BOLD);
        btn_focus.setBackground(getDrawable(R.drawable.button_border_yellow));
        this.btn_unfocus = btn_focus;
    }

    private void setupRecyclerView(@NonNull RecyclerView recyclerView, List<Presentation.IdAndPresentationTuple> ITEMS) {
        mAdapter = new ItemRecyclerViewAdapter(this, ITEMS, mTwoPane);
        recyclerView.setHasFixedSize(true);
        recyclerView.setAdapter(mAdapter);
        recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
    }
}

ItemRecyclerViewAdapter

public class ItemRecyclerViewAdapter extends RecyclerView.Adapter<ItemRecyclerViewAdapter.ViewHolder> {

    private final ProductListActivity mParentActivity;
    private final List<Presentation.IdAndPresentationTuple> mValues;
    private final boolean mTwoPane;

    ItemRecyclerViewAdapter(ProductListActivity parent,
                            List<Presentation.IdAndPresentationTuple> items,
                            boolean twoPane) {
        mParentActivity = parent;
        mValues = items;
        mTwoPane = twoPane;
    }

    // My custom method to clear, update and notifyDataSetChanged
    public void updateData(List<Presentation.IdAndPresentationTuple> items) {
        mValues.clear();
        mValues.addAll(items);
        notifyDataSetChanged();
    }

    private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Presentation.IdAndPresentationTuple item = (Presentation.IdAndPresentationTuple) view.getTag();
            if (mTwoPane) {
                Bundle arguments = new Bundle();
                // Send the id of the product to show
                arguments.putString(ProductDetailFragment.ARG_ITEM_ID, String.valueOf(item.getId()));
                ProductDetailFragment fragment = new ProductDetailFragment();
                fragment.setArguments(arguments);
                mParentActivity.getSupportFragmentManager().beginTransaction()
                        .replace(R.id.product_detail_container, fragment)
                        .commit();
            } else {
                Context context = view.getContext();
                Intent intent = new Intent(context, ProductDetailActivity.class);
                intent.putExtra(ProductDetailFragment.ARG_ITEM_ID, String.valueOf(item.getId()));

                context.startActivity(intent);
            }
        }
    };

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

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
        holder.mIdView.setText(String.valueOf(mValues.get(position).getId()));
        holder.mRepresentationNameView.setText(mValues.get(position).getPresentationName());

        holder.itemView.setTag(mValues.get(position));
        holder.itemView.setOnClickListener(mOnClickListener);
    }

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

    class ViewHolder extends RecyclerView.ViewHolder {
        final TextView mIdView;
        final TextView mRepresentationNameView;

        ViewHolder(View view) {
            super(view);
            mIdView = (TextView) view.findViewById(R.id.id);
            mRepresentationNameView = (TextView) view.findViewById(R.id.representationName);
        }
    }

}

我的目标是每次单击新按钮(产品)时 update/refresh RecyclerView 正确。

一切看起来都很好。只需进行以下更改:

  1. 您已经在以下位置设置了空数据的 recyclerView:

    setupRecyclerView((RecyclerView) recyclerView, null);

因此,您无需在第一个按钮中再次设置它。

  1. 在您的适配器中,在方法 getItemCount()

    中添加以下更改

    @Override public int getItemCount() { 如果(mValues==null) return 0;

    return mValues.size(); }

通过这段代码,您是在告诉适配器,在开始时,当 mValues 为 null 时,将不会显示任何数据。因此,项目计数设置为 0。

更新

  1. 不要以编程方式单击第一个按钮,仅在应用程序打开时显示一些数据。虽然没什么问题,但这不是一个好的编码习惯。

在 onCreate() 中,调用您的 setupRecyclerView() 以显示第一个按钮的数据。

更改如下:

ProductListActivity

public class ProductListActivity extends AppCompatActivity implements View.OnClickListener {

    /**
     * Whether or not the activity is in two-pane mode, i.e. running on a tablet
     * device.
     */
    private boolean mTwoPane;

    // Group of buttons
    private Button[] btn = new Button[4];
    private Button btn_unfocus;
    private int[] btn_id = {R.id.btn0, R.id.btn1, R.id.btn2, R.id.btn3};

    private View recyclerView;
    private ItemRecyclerViewAdapter mAdapter;
    private MyDatabase mMyDatabase;

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

        if (findViewById(R.id.product_detail_container) != null) {
            // The detail container view will be present only in the
            // large-screen layouts (res/values-w900dp).
            // If this view is present, then the
            // activity should be in two-pane mode.
            mTwoPane = true;
        }

        mMyDatabase = Utils.getDatabase(ProductListActivity.this);

        recyclerView = findViewById(R.id.product_list);

       //Get the data that you want to display for the first time
        List<Presentation.IdAndPresentationTuple> presentationList1 = mMyDatabase.presentationDao()
                        .getProductRepresentationsByName("Product 1");


                // Set up recycler view for the first time

               setupRecyclerView((RecyclerView) recyclerView, presentationList1);

                mAdapter.updateData(presentationList1); //Call the update method

        // Initialize the button group
        initButtonGroup();
    }

    private void initButtonGroup() {
        for(int i = 0; i < btn.length; i++){
            btn[i] = (Button) findViewById(btn_id[i]);
            btn[i].setBackgroundColor(ContextCompat.getColor(this, R.color.customGreenDark));
            btn[i].setTextColor(Color.WHITE);
            btn[i].setOnClickListener(this);
        }

        btn_unfocus = btn[0];

        // Set the first button clicked by default
        //btn[0].performClick(); //Don't perform manual click
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn0 :
                setFocus(btn_unfocus, btn[0]);
                List<Presentation.IdAndPresentationTuple> presentationList1 = mMyDatabase.presentationDao()
                        .getProductRepresentationsByName("Product 1");

                mAdapter.updateData(presentationList1);
                break;

            case R.id.btn1:
                setFocus(btn_unfocus, btn[1]);
                List<Presentation.IdAndPresentationTuple> presentationList2 = mMyDatabase.presentationDao()
                        .getProductRepresentationsByName("Product 2");
                // Update data
                mAdapter.updateData(presentationList2);
                break;

            case R.id.btn2:
                setFocus(btn_unfocus, btn[2]);
                List<Presentation.IdAndPresentationTuple> presentationList3 = mMyDatabase.presentationDao()
                        .getProductRepresentationsByName("Product 3");
                // Update data
                mAdapter.updateData(presentationList3);
                break;
        }
    }

    private void setFocus(Button btn_unfocus, Button btn_focus){
        btn_unfocus.setTextColor(Color.WHITE);
        btn_unfocus.setTypeface(null, Typeface.NORMAL);
        btn_unfocus.setBackgroundColor(ContextCompat.getColor(this, R.color.customGreenDark));
        btn_focus.setTextColor(Color.BLACK);
        btn_focus.setTypeface(null, Typeface.BOLD);
        btn_focus.setBackground(getDrawable(R.drawable.button_border_yellow));
        this.btn_unfocus = btn_focus;
    }

    private void setupRecyclerView(@NonNull RecyclerView recyclerView, List<Presentation.IdAndPresentationTuple> ITEMS) 
    {


        if(recyclerView.getAdapter()==null)
        {
            //Set the Adapter for the first time only 
             mAdapter = new ItemRecyclerViewAdapter(this, null, mTwoPane);
              recyclerView.setHasFixedSize(true);
              recyclerView.setAdapter(mAdapter);
              recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
        }

    }
}

ItemRecyclerViewAdapter

public class ItemRecyclerViewAdapter extends RecyclerView.Adapter<ItemRecyclerViewAdapter.ViewHolder> {

    private final ProductListActivity mParentActivity;
    private final List<Presentation.IdAndPresentationTuple> mValues;
    private final boolean mTwoPane;

    ItemRecyclerViewAdapter(ProductListActivity parent,
                            List<Presentation.IdAndPresentationTuple> items,
                            boolean twoPane) {
        mParentActivity = parent;
        mValues = items;
        mTwoPane = twoPane;
    }

    // My custom method to clear, update and notifyDataSetChanged
    public void updateData(List<Presentation.IdAndPresentationTuple> items) 
    {
        if(items!=null)
        {
             mValues.clear();
            mValues.addAll(items);
            notifyDataSetChanged();
        }

    }

    private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Presentation.IdAndPresentationTuple item = (Presentation.IdAndPresentationTuple) view.getTag();
            if (mTwoPane) {
                Bundle arguments = new Bundle();
                // Send the id of the product to show
                arguments.putString(ProductDetailFragment.ARG_ITEM_ID, String.valueOf(item.getId()));
                ProductDetailFragment fragment = new ProductDetailFragment();
                fragment.setArguments(arguments);
                mParentActivity.getSupportFragmentManager().beginTransaction()
                        .replace(R.id.product_detail_container, fragment)
                        .commit();
            } else {
                Context context = view.getContext();
                Intent intent = new Intent(context, ProductDetailActivity.class);
                intent.putExtra(ProductDetailFragment.ARG_ITEM_ID, String.valueOf(item.getId()));

                context.startActivity(intent);
            }
        }
    };

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

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
        holder.mIdView.setText(String.valueOf(mValues.get(position).getId()));
        holder.mRepresentationNameView.setText(mValues.get(position).getPresentationName());

        holder.itemView.setTag(mValues.get(position));
        holder.itemView.setOnClickListener(mOnClickListener);
    }

    @Override
    public int getItemCount() 
    {
        if(mValues==null)
        {
            return 0;
        }
        return mValues.size();
    }

    class ViewHolder extends RecyclerView.ViewHolder {
        final TextView mIdView;
        final TextView mRepresentationNameView;

        ViewHolder(View view) {
            super(view);
            mIdView = (TextView) view.findViewById(R.id.id);
            mRepresentationNameView = (TextView) view.findViewById(R.id.representationName);
        }
    }

}