简体   繁体   中英

Update RecyclerView with new data in MasterDetail Flow

I'm doing a Mobile App for Tablets and I have added a Master/Detail Flow using the Android Studio steps. I have a group of 4 buttons above the Master Detail to select a "Product" and then, when you clic one of them, the RecyclerView is updated with data.

My problem is that if you clic one button (a product), then another, and another, etc.. All data is loaded together so, I need to figure out how to update/refresh the RecyclerView.

在此处输入图片说明

In my RecyclerViewAdapter I have added a method to clear, update the ITEMS and then, notifyDataSetChanged. This is working good for the rest of the buttons but, not for the first button which is clicked by default programatically. The first button set up the RecyclerView again.

在此处输入图片说明

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);
        }
    }

}

My goal is to update/refresh the RecyclerView properly every time you click a new button (Product).

Everything looks good. Just make the following changes:

  1. You are already setting the recyclerView with null data at:

    setupRecyclerView((RecyclerView) recyclerView, null);

So, you don't need to set it again in your first button.

  1. In your Adapter, add the following change in the method getItemCount()

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

    return mValues.size(); }

With this code, you are telling the adapter that at the beginning, when mValues will be null, there will be no data to be displayed. Therefore the item count is set to 0.

Update

  1. Don't programmatically click the first button only to show some data when the app opens. Though nothing is wrong, it is not a good coding practice.

Inside onCreate(), call your setupRecyclerView() to get display the data of the first button.

Here is the change :

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);
        }
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM