具有重复值的回收站更新

Posted

技术标签:

【中文标题】具有重复值的回收站更新【英文标题】:Recycler updates with duplicate values 【发布时间】:2019-12-10 10:27:16 【问题描述】:

我使用擦除删除方法来删除一行,当我从回收器列表视图中删除一行时,它会复制我已删除的值下方的值。 如果我从列表中删除“测试 3”

它在第 3 和第 4 位显示重复的“测试 4”

我用于创建和删除列表的整个代码,任何人都可以帮我解决这个问题

public class fragmnetPendingAct extends Fragment 

    private SwipeRefreshLayout refreshLayout;
    private RecyclerView recyclerView;

    ArrayList<String> activitynames;

    FirebaseAuth mAuth;
    View view;

    List<modelclasspendingact> modelclasspendingactList = new ArrayList<>();



    public fragmnetPendingAct() 
    

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) 
        View v = inflater.inflate(R.layout.fragment_pendingactivity,container,false);

        refreshLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_activitypend);

        recyclerView = v.findViewById(R.id.recyclerviewpendingact);
        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);

        recyclerView.setLayoutManager(layoutManager);


        new ItemTouchHelper(itemtouchHelpercalback).attachToRecyclerView(recyclerView);







        //listen to swipe horizontal
        refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() 
            @Override
            public void onRefresh() 

                // Get new Instance ID token
                FirebaseUser mUser = mAuth.getInstance().getCurrentUser();
                mUser.getIdToken(true)
                        .addOnCompleteListener(new OnCompleteListener<GetTokenResult>() 
                            public void onComplete(@NonNull Task<GetTokenResult> task) 
                                if (task.isSuccessful()) 
                                    String token = task.getResult().getToken();
                                    // Send token to your backend via HTTPS
                                    getdatafromserver(token);

                                 else 
                                    // Handle error -> task.getException();
                                    Log.w(TAG, "getInstanceId failed second", task.getException());

                                
                            
                        );


                refreshitems();
            
        );







        // Get new Instance ID token
        FirebaseUser mUser = mAuth.getInstance().getCurrentUser();
        mUser.getIdToken(true)
                .addOnCompleteListener(new OnCompleteListener<GetTokenResult>() 
                    public void onComplete(@NonNull Task<GetTokenResult> task) 
                        if (task.isSuccessful()) 
                            String token = task.getResult().getToken();
                            Log.d(TAG, "onComplete lead: "+token);
                            // Send token to your backend via HTTPS
                            getdatafromserver(token);

                         else 
                            // Handle error -> task.getException();
                            Log.w(TAG, "getInstanceId failed second", task.getException());

                        
                    
                );




        return v;
    






    public void getdatafromserver(String token)

        //new code using curl
        String serverurl="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, serverurl,null,
                new Response.Listener<JSONObject>() 
                    @Override
                    public void onResponse(JSONObject response) 
                        try 
                            Log.d(TAG, "activity list: "+response);


                            JSONObject alldata=response.getJSONObject("payload");

                            JSONArray assetaarray=alldata.getJSONArray("activities");



                            modelclasspendingactList.removeAll(modelclasspendingactList);


                            for(int i=0;i<assetaarray.length();i++)
                            
                              JSONObject getactivity=assetaarray.getJSONObject(i);
                              String activityid = String.valueOf(getactivity.getInt("id"));
                              String activityname = getactivity.getString("title");
                              String activitydesc = getactivity.getString("description");
                                Log.d(TAG, "activity name: "+activityname);


                                //list crreation
                                modelclasspendingactList.add(new modelclasspendingact(activityname,activitydesc,activityid));
                                pendingactAdapter adapter = new pendingactAdapter(modelclasspendingactList);
                                recyclerView.setAdapter(adapter);
                                adapter.notifyDataSetChanged();



                            




                        
                        catch (JSONException e) 
                            e.printStackTrace();
                        
                    
                , new Response.ErrorListener() 
            @Override
            public void onErrorResponse(VolleyError error) 

                error.printStackTrace();

            
        
        )
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError 
                Map<String,String> headers=new HashMap<String,String>();
                headers.put("Accept","*/*");
                headers.put("Cache-Control","no-cache");
                headers.put("cache-control","no-cache");
                headers.put("token",token);

                return headers;
            
        ;
        singletonclasshttp.getInstance(getActivity()).addtorequestque(jsonObjectRequest);



    


    private void refreshitems()
    

        refreshLayout.setRefreshing(false);

    

    //swipe function
    ItemTouchHelper.SimpleCallback itemtouchHelpercalback = new ItemTouchHelper.SimpleCallback(0,ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) 
        @Override
        public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder viewHolder1) 
            return false;
        

        @Override
        public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) 

            Log.d(TAG, "onSwiped: "+modelclasspendingactList.get(viewHolder.getAdapterPosition()).getPendid());
            Log.d(TAG, "onSwiped: position "+viewHolder.getAdapterPosition());

            String activeid = modelclasspendingactList.get(viewHolder.getAdapterPosition()).getPendid();


            // Get new Instance ID token
            FirebaseUser mUser = mAuth.getInstance().getCurrentUser();
            mUser.getIdToken(true)
                    .addOnCompleteListener(new OnCompleteListener<GetTokenResult>() 
                        public void onComplete(@NonNull Task<GetTokenResult> task) 
                            if (task.isSuccessful()) 
                                String token = task.getResult().getToken();
                                //send token and activity id to update function
                                markascompleted(activeid,token);


                             else 
                                // Handle error -> task.getException();
                                Log.w(TAG, "getInstanceId failed second", task.getException());

                            
                        
                    );

            Log.d(TAG, "onSwiped: position "+viewHolder.getAdapterPosition());
            Log.d(TAG, "onSwiped: first list size "+modelclasspendingactList.size());


            pendingactAdapter adapter = new pendingactAdapter(modelclasspendingactList);
            modelclasspendingactList.remove(viewHolder.getAdapterPosition());
            recyclerView.removeViewAt(viewHolder.getAdapterPosition());
            adapter.notifyItemRemoved(viewHolder.getAdapterPosition());
//            adapter.notifyItemRangeChanged(viewHolder.getAdapterPosition(), modelclasspendingactList.size());
//            adapter.notifyDataSetChanged();
            Log.d(TAG, "onSwiped: list size "+modelclasspendingactList.size());



//            pendingactAdapter adapter = new pendingactAdapter(modelclasspendingactList);
//            modelclasspendingactList.remove(viewHolder.getAdapterPosition());
//            adapter.notifyItemRemoved(viewHolder.getAdapterPosition());


        
    ;





    private void markascompleted(String activeid,String token)
    
        //send data to server
        //curl function

        String serverurl="xxxxxxxxxxxxxxxxxxxxxxx";

        Map<String, Object> jsonParams = new ArrayMap<>();
        jsonParams.put("id", activeid);
        jsonParams.put("activityStatus", "COMPLETED");
        jsonParams.put("targetEmployeeId", "1001");
        jsonParams.put("score", "1");



        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.PUT, serverurl,new JSONObject(jsonParams),
                new Response.Listener<JSONObject>() 
                    @Override
                    public void onResponse(JSONObject response) 

                        Log.d(TAG, "response: "+response);


                        try 
                            if (response.optBoolean("success")==true)
                            

                                Toast.makeText(getActivity(), response.getString("message"),Toast.LENGTH_LONG).show();

                            
                            else
                            

                                Toast.makeText(getActivity(),"Data Not Updated",Toast.LENGTH_LONG).show();
                            

                         catch (JSONException e) 
                            Toast.makeText(getActivity(),"Data Not Updated",Toast.LENGTH_LONG).show();
                            e.printStackTrace();
                        

                    
                , new Response.ErrorListener() 
            @Override
            public void onErrorResponse(VolleyError error) 

                Toast.makeText(getActivity(),"Data Not Saved",Toast.LENGTH_SHORT).show();
                error.printStackTrace();
            
        
        )

            @Override
            public Map<String, String> getHeaders() throws AuthFailureError 
                Map<String,String> headers=new HashMap<String,String>();
                headers.put("Accept","*/*");
                headers.put("Cache-Control","no-cache");
                headers.put("Connection","keep-alive");
                headers.put("Content-Type","application/json");
                headers.put("cache-control","no-cache");
                headers.put("token",token);
                return headers;
            
        ;

        singletonclasshttp.getInstance(getActivity()).addtorequestque(jsonObjectRequest);

    


【问题讨论】:

notifyItemRemoved 在此之后您不需要 notifyDataSetChanged @AnasMehar 问题仍然存在 可以在 notifyDataSetChanged 后使用调试检查你的适配器列表 list.size()。 @AlvinJohnNiravukalayil 不要打电话给notifyItemRangeChanged() @AnasMehar 最初为 6,删除时为 5 【参考方案1】:

首先我会解释为什么会出现这种行为,然后我们会找到解决方案。 在这段代码中:

问题 1:

pendingactAdapter adapter = new pendingactAdapter(modelclasspendingactList);

您正在创建一个适配器并将您的 当前 数据传递给它。请注意,适配器将拥有您在构造函数中传递的列表的自己的副本。

modelclasspendingactList.remove(viewHolder.getAdapterPosition());

您要从中删除项目的列表与您刚刚在适配器中发送的列表不同,因此适配器仍有旧列表。 然后你调用removed,适配器尝试更新值,但你删除的项目仍在适配器的列表中。

解决方案: 在适配器中创建一个函数/方法,从适配器列表中删除项目

问题 #2 的解决方案: 每次滑动视图时,您都在创建一个新的适配器实例/对象,这是不必要的。在类而不是函数中创建适配器,并在 onCreateView() 中实例化它。

【讨论】:

非常感谢兄弟。你救了我。【参考方案2】:

几件事。

首先,removeViewAtRecyclerView.LayoutManager 的函数。我想你是想说recyclerView.LayoutManager.removeViewAt

其次,调用removeViewAt 应该是不必要的,因为当notifyItemRemoved 被正确调用时,RecyclerView 会自动执行此操作。

第三,删除项目时不需要重新绑定整个列表。您可以删除notifyItemRangeChanged

第四,您也不需要在删除项目时使整个适配器无效。您可以删除notifyDataSetChanged。事实上,这个功能只能作为最后的手段使用。

初始化你的RecyclerView:

pendingactAdapter adapter = new pendingactAdapter(modelclasspendingactList);
RecyclerView recyclerView = view.findViewById(R.id.my_recycler_view);
recyclerView.adapter = adapter;
recyclerView.layoutManager = LinearLayoutManager(getActivity());

所以你的删除顺序应该是

 modelclasspendingactList.remove(viewHolder.getAdapterPosition());
 adapter.notifyItemRemoved(viewHolder.getAdapterPosition());

【讨论】:

但是当我使用此代码时它会删除但它不对齐,删除的行中有一个间隙。 这似乎是布局管理器的问题。使用显示您如何初始化回收站视图的代码更新您的问题。我在答案中添加了一个示例。 我已经用整个代码更新了我的问题。我得到了解决方案,谢谢你的回答。

以上是关于具有重复值的回收站更新的主要内容,如果未能解决你的问题,请参考以下文章

具有全屏缩放的 ImageView

Recycler View Android中的Firestore数据[重复]

一次滑动一项Recyclerview [重复]

滚动回收站视图时如何防止项目重复

为recyclerview更新帖子的评论数

将视图插入回收站视图 [重复]