android - RecyclerView每秒更新一次并拥有一个longPressListener

时间:2016-10-24 09:14:14

标签: android android-recyclerview notifydatasetchanged long-press

我有一个nottifyDataSetChanged在每个列表项中都有一个计数器,因为调用了计数器回调,它更新了相关字段并调用了public void setCountDown(int countDown){ mCountDown = countDown; notifyDataSetChanged(); }

它工作正常,但问题是,我还有一个长按监听器,因为当用户按下项目时数据被更新,压力机丢失

我该如何处理?

更新代码:

    holder.container.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            FragmentManager fm = ((AppCompatActivity)activity).getSupportFragmentManager();
            EditAccountFragment editAccountFragmentDialog = EditAccountFragment.newInstance(_id);
            editAccountFragmentDialog.show(fm, "fragment_edit_account");

            return false;
        }
    });

长按一下监听器:

public class AccountAdapter extends RecyclerView.Adapter<AccountAdapter.ItemViewHolder> {

    private static final String TAG = "ITEM_ADAPTER";

    private Cursor itemCursor;
    private Activity activity;
    private ItemColumnIds feedColumnIds;
    private int mCountDown;
    private boolean ignoreDatasetChange = false;

    /**
     * initilaizer for recycler view adapter, takes in activity although better way is to handle
     * activity related tasks within activiyt, but this is just done to speed up the overall process
     * @param activity
     */
    public AccountAdapter(Activity activity){
        this.activity = activity;
    }

    @Override
    public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(activity).inflate(R.layout.account_item,
                parent, false);

        feedColumnIds = new ItemColumnIds();

        if (itemCursor != null){
            // initilize column indices information
            feedColumnIds.colId = itemCursor.getColumnIndex(
                    AuthContract.AccountEntry._ID);
            feedColumnIds.colAcctId = itemCursor.getColumnIndex(
                    AuthContract.AccountEntry.COLUMN_USERNAME);
            feedColumnIds.colPin = itemCursor.getColumnIndex(
                    AuthContract.AccountEntry.COLUMN_PIN);
            feedColumnIds.colIssuer = itemCursor.getColumnIndex(
                    AuthContract.AccountEntry.COLUMN_ISSUER);
        }

        return new ItemViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final ItemViewHolder holder, int position) {

        if(itemCursor == null)
            return;

        if(!itemCursor.moveToPosition(position))
            return;

        //get values from cursor
        String pin = itemCursor.getString(feedColumnIds.colPin);
        String email = itemCursor.getString(feedColumnIds.colAcctId);
        String issuer = itemCursor.getString(feedColumnIds.colIssuer);
        final long _id = itemCursor.getLong(feedColumnIds.colId);


        //set view values
        holder.tvEmail.setText(email);
        holder.tvPin.setText(pin);
        holder.tvIssuer.setText(issuer);
        holder.apCountDown.setProgress(mCountDown);

        holder.container.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String pin = holder.tvPin.getText().toString();
                ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
                ClipData clip = ClipData.newPlainText("Secret Key", pin);
                clipboard.setPrimaryClip(clip);

                Toast.makeText(activity, "OTP code "+ pin +" copied to clipboard", Toast.LENGTH_SHORT).show();

            }
        });

        holder.container.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                FragmentManager fm = ((AppCompatActivity)activity).getSupportFragmentManager();
                EditAccountFragment editAccountFragmentDialog = EditAccountFragment.newInstance(_id);
                editAccountFragmentDialog.show(fm, "fragment_edit_account");

                return false;
            }

        });

    }

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



    /**
     * close previurous cursor if any and replace that with the new on from host class
     * @param cursor
     */
    public void swapCursor(Cursor cursor) {
        if(itemCursor != null) {
            itemCursor.close();
            itemCursor = null;
        }

        itemCursor = cursor;
        notifyDataSetChanged();

    }

    public void setCountDown(int countDown){
        mCountDown = countDown;

        if(!ignoreDatasetChange)
            notifyDataSetChanged();
    }

    /**
     * View golder for auction item entry
     */
    public class ItemViewHolder extends RecyclerView.ViewHolder {
        TextView tvEmail;
        TextView tvPin;
        TextView tvIssuer;
//        TextView tvCountDown;
        ArcProgress apCountDown;
        View container;

        public ItemViewHolder(View itemView) {
            super(itemView);
            tvEmail = (TextView) itemView.findViewById(R.id.tv_email);
            tvPin = (TextView) itemView.findViewById(R.id.tv_pin);
            tvIssuer = (TextView) itemView.findViewById(R.id.tv_issuer);
            apCountDown = (ArcProgress) itemView.findViewById(R.id.arc_progress);
            container = itemView.findViewById(R.id.container);
        }
    }

    /**
     * databse column id holder for auction item
     */
    class ItemColumnIds {

        public int colId;
        public int colPin;
        public int colAcctId;
        public int colIssuer;

    }

}

根据请求添加适配器

CREATE TABLE [dbo].[AIRQUALITYTS2]
(
    [FeatureID] [nvarchar](20) NOT NULL,
    [ParameterID] [nvarchar](20) NOT NULL,
    [MeasurementDateTime] [datetime2](7) NOT NULL,
    [ParameterValue] [numeric](38, 8) NULL,
    [Remarks] [nvarchar](150) NULL,

    CONSTRAINT [PK_AIRQUALITYTS2] 
        PRIMARY KEY CLUSTERED ([FeatureID] ASC, [ParameterID] ASC, [MeasurementDateTime] ASC)
                    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                          IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                          ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

3 个答案:

答案 0 :(得分:2)

修正了它!

所以基本上问题是,每当碰巧有一个更新来反击整个适配器时,填充整个视图,包括监听器,甚至在ViewHolder中设置监听器都不起作用。

我做了什么,我扩展了我的布局管理器并添加了一个方法来仅更新视图的计数器小部件,而其他部分保持不变。

这是TimedGridLayoutManager:

public class TimedGridLayoutManager extends GridLayoutManager {

   public TimedGridLayoutManager(Context context, int spanCount) {
        super(context, spanCount);
    }

    //updates the counter every second
    public void setCountDown(int countDown) {
        //return null if there are no items and avoid crash
        if(this.getItemCount() <= 0)
            return;

        //get first and last visible child
        int firstPos = this.findFirstVisibleItemPosition();
        int lastPos = this.findLastVisibleItemPosition();

        //loop through the range and set counter
        for(int i = firstPos; i <= lastPos; i++) {
            View itemView = this.findViewByPosition(i);
            ArcProgress arcCounter = (ArcProgress) itemView.findViewById(R.id.arc_counter);
            arcCounter.setProgress(countDown);

        }
    }
}

它不知道它是否是最有效的解决方案,但它对我来说就像一个魅力,而且我根本不需要触摸我的适配器代码。

答案 1 :(得分:1)

我认为您应该考虑在用户触摸视图时停止快速刷新。

为此,您只需实现onTouchEvent,并在检测到MotionEvent.ACTION_DOWN时设置标志。

...
if (event.getAction()==MotionEvent.ACTION_DOWN) isUserTouching = true;
if (event.getAction()==MotionEvent.ACTION_UP) isUserTouching = false;
...

然后,您更新代码变为:

public void setCountDown(int countDown){
   if (!isUserTouching) {
      mCountDown = countDown;
      notifyDataSetChanged();
   }
}

答案 2 :(得分:0)

您必须在创建视图持有者时设置单击和长按侦听器,而不是在视图持有者的绑定中。

将您的观看者更新为:

public class ItemViewHolder extends RecyclerView.ViewHolder {
        TextView tvEmail;
        TextView tvPin;
        TextView tvIssuer;
//        TextView tvCountDown;
        ArcProgress apCountDown;
        View container;

        public ItemViewHolder(View itemView) {
            super(itemView);
            tvEmail = (TextView) itemView.findViewById(R.id.tv_email);
            tvPin = (TextView) itemView.findViewById(R.id.tv_pin);
            tvIssuer = (TextView) itemView.findViewById(R.id.tv_issuer);
            apCountDown = (ArcProgress) itemView.findViewById(R.id.arc_progress);
            container = itemView.findViewById(R.id.container);

            container.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    String pin = tvPin.getText().toString();
                    ClipboardManager clipboard = (ClipboardManager) itemView.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
                    ClipData clip = ClipData.newPlainText("Secret Key", pin);
                    clipboard.setPrimaryClip(clip);

                    Toast.makeText(itemView.getContext(), "OTP code "+ pin +" copied to clipboard", Toast.LENGTH_SHORT).show();

                }
            });

            container.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    FragmentManager fm = ((AppCompatActivity)itemView.getContext()).getSupportFragmentManager();
                    EditAccountFragment editAccountFragmentDialog = EditAccountFragment.newInstance(_id);
                    editAccountFragmentDialog.show(fm, "fragment_edit_account");

                    return true; //if you handle it, return true!
                }

            });
        }
    }

并删除holder.container.setOnClickListener方法中的holder.container.setOnLongClickListeneronBindViewHolder