Search code examples
javaandroidandroid-recyclerviewandroid-cardviewcustom-adapter

How to update item in RecycleView?


I am creating Application in which I have give functionality like Facebook timeline where people can update their story and any user can like or comment on the story. Everything is working fine but what I am facing issue is that when any user update story then data of updated story get saved on server but not added in recycle view at same time. When User go back and again comes on timeline screen then list will get update. How can I solve this problem ?

Custom Adapter

public class TimeLineListAdapter extends RecyclerView.Adapter<TimeLineListAdapter.ViewHolder> {
    private List<TimeLineItem> timeLineItems;
    String message, storyId, token;
    private Context context;
    ImageLoader imageLoader = AppController.getInstance().getImageLoader();

    public TimeLineListAdapter(List<TimeLineItem> timeLineItems, Context context) {
        super();
        this.context = context;
        this.timeLineItems = timeLineItems;
    }

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

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

        //Getting the particular item from the list
        TimeLineItem item =  timeLineItems.get(position);

        if (item.getTotalLikes().equals("0")){
            holder.txtLike.setText("");
        }else {
            holder.txtLike.setText(item.getTotalLikes());
        }

        if (item.getTotalComment().equals("0")){
            holder.txtComment.setText("");
        }else {
            holder.txtComment.setText("("+item.getTotalComment()+")");
        }

        if (item.getIsLike() == 0){

        }else {
            holder.imageLike.setImageBitmap(null);
            holder.imageLike.setBackgroundResource(R.drawable.islike);
            holder.txtLike.setTextColor(Color.parseColor("#3498db"));
        }

        holder.name.setText(item.getName() + " " + item.getLname());


        /*Long.parseLong(item.getTimeStamp()),
                System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS);*/
        holder.timestamp.setText(item.getTimeStamp());

        // Chcek for empty status message
        if (!TextUtils.isEmpty(item.getStatus())) {
            holder.statusMsg.setText(item.getStatus());
            holder.statusMsg.setVisibility(View.VISIBLE);
        } else {
            // status is empty, remove from view
            holder.statusMsg.setVisibility(View.GONE);
        }

        // Checking for null feed url
        if (item.getUrl() != null) {
            holder.url.setText(Html.fromHtml("<a href=\"" + item.getUrl() + "\">"
                    + item.getUrl() + "</a> "));

            // Making url clickable
            holder.url.setMovementMethod(LinkMovementMethod.getInstance());
            holder.url.setVisibility(View.VISIBLE);
        } else {
            // url is null, remove from the view
            holder.url.setVisibility(View.GONE);
        }

        // user profile pic
        holder.profilePic.setImageUrl(item.getProfilePic(), imageLoader);

        // Feed image
        if (item.getImge() != null) {
            holder.feedImageView.setImageUrl(item.getImge(), imageLoader);
            holder.feedImageView.setVisibility(View.VISIBLE);
            holder.feedImageView
                    .setResponseObserver(new TimeLineImageView.ResponseObserver() {
                        @Override
                        public void onError() {
                        }

                        @Override
                        public void onSuccess() {
                        }
                    });
        } else {
            holder.feedImageView.setVisibility(View.GONE);
        }

        holder.txtComment.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                final TimeLineItem m = timeLineItems.get(position);
                String ide = String.valueOf(m.getId());

                Intent intent = new Intent(context, StoryDetailActivity.class);
                intent.putExtra("storyId",ide);
                context.startActivity(intent);
            }
        });

        holder.txtCommentLabel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final TimeLineItem m = timeLineItems.get(position);
                String ide = String.valueOf(m.getId());

                Intent intent = new Intent(context, StoryDetailActivity.class);
                intent.putExtra("storyId",ide);
                context.startActivity(intent);
            }
        });


        holder.imageLike.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {

                TimelineActivity t = new TimelineActivity();

                final TimeLineItem m = timeLineItems.get(position);
                String ide = String.valueOf(m.getId());

                likeStory(ide,t.token);

                return false;
            }
        });

    }

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

    class ViewHolder extends RecyclerView.ViewHolder{

        TextView name, timestamp, statusMsg, url, txtLike, txtComment, txtCommentLabel;
        NetworkImageView profilePic;
        TimeLineImageView feedImageView;
        ImageView imageLike;

        //Initializing Views
        public ViewHolder(View itemView) {
            super(itemView);
            name = (TextView) itemView.findViewById(R.id.name);
            timestamp = (TextView) itemView.findViewById(R.id.timestamp);
            statusMsg = (TextView) itemView.findViewById(R.id.txtStatusMsg);
            url = (TextView) itemView.findViewById(R.id.txtUrl);
            profilePic = (NetworkImageView) itemView.findViewById(R.id.profilePic);
            feedImageView = (TimeLineImageView) itemView.findViewById(R.id.feedImage1);
            imageLike = (ImageView) itemView.findViewById(R.id.imgLike);
            txtLike = (TextView) itemView.findViewById(R.id.txtLike);
            txtComment = (TextView) itemView.findViewById(R.id.txtComment);
            txtCommentLabel = (TextView) itemView.findViewById(R.id.txtCommentLabel);
        }
    }

    private void likeStory(final String story_id, final String token) {
        // Tag used to cancel the request
        String tag_string_req = "req_register";

        StringRequest strReq = new StringRequest(Request.Method.POST, AppConfig.likeStory, new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {

                try {
                    JSONObject jObj = new JSONObject(response);
                    boolean error = jObj.getBoolean("status");
                    message = jObj.getString("message");
                    if (error) {

                    } else {

                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                Toast.makeText(context, "Oops something went wrong...", Toast.LENGTH_LONG).show();
            }
        }) {

            @Override
            protected Map<String
                    , String> getParams() {
                // Posting params to register url
                Map<String, String> params = new HashMap<String, String>();
                params.put("my_token", token);
                params.put("story_id", story_id);

                return params;
            }

        };

        // Adding request to request queue
        AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
    }

}

TimeLineActivity

public void getTimeLineData(final String token, final String page) {


        String tag_string_req = "req_register";
        // making fresh volley request and getting json
        StringRequest strReq = new StringRequest(Request.Method.POST, AppConfig.timeline, new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                VolleyLog.d(TAG, "Response: " + response.toString());
                if (response != null) {
                    try {
                        JSONObject jObj = new JSONObject(response);
                        boolean error = jObj.getBoolean("status");
                        String message = jObj.getString("message");
                        if (error) {
                            totalPages = jObj.getInt("totalPages");
                            pageCount = jObj.getInt("page");

                            int limit = jObj.getInt("limit");
                            parseJsonFeed(response);
                        }

                    } catch (Exception e) {

                    }

                }
            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                VolleyLog.d(TAG, "Error: " + error.getMessage());
            }
        }) {

            @Override
            protected Map<String, String> getParams() {
                // Posting params to register url
                Map<String, String> params = new HashMap<String, String>();
                params.put("my_token", token);
                params.put("page", page);
                params.put("limit", "5");

                return params;
            }
        };

        // Adding request to request queue
        AppController.getInstance().addToRequestQueue(strReq, tag_string_req);

    }

    private void parseJsonFeed(String response) {
        try {
            JSONObject jsonObj = new JSONObject(response);
            JSONArray feedArray = jsonObj.getJSONArray("data");

            for (int i = 0; i < feedArray.length(); i++) {
                JSONObject feedObj = (JSONObject) feedArray.get(i);

                TimeLineItem item = new TimeLineItem();
                item.setId(feedObj.getInt("id"));
                item.setName(feedObj.getString("name"));
                item.setLname(feedObj.getString("lname"));

                // Image might be null sometimes
                String image = feedObj.isNull("image") ? null : feedObj
                        .getString("image");

                if (image.equals("")) {
                    item.setImge(image);
                } else {
                    item.setImge(AppConfig.storyPic + image);
                }

                item.setStatus(feedObj.getString("story_text"));
                item.setProfilePic(AppConfig.profilePic + feedObj.getString("profile_pic"));
                item.setTimeStamp(feedObj.getString("time_stamp"));
                item.setIsLike(feedObj.getInt("is_like"));
                item.setTotalLikes(feedObj.getString("total_likes"));
                item.setTotalComment(feedObj.getString("total_comments"));

                /*// url might be null sometimes
                String feedUrl = feedObj.isNull("url") ? null : feedObj
                        .getString("url");
                item.setUrl(feedUrl);*/

                timeLineItems.add(item);
            }

            // notify data changes to list adapater
            adapter.notifyDataSetChanged();


        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

private void addStory(final String story_text, final String token, final String image) {
        // Tag used to cancel the request
        String tag_string_req = "req_register";

        pDialog.setMessage("Please wait ...");
        showDialog();

        StringRequest strReq = new StringRequest(Request.Method.POST, AppConfig.addStory, new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                hideDialog();

                try {
                    JSONObject jObj = new JSONObject(response);
                    boolean error = jObj.getBoolean("status");
                    message = jObj.getString("message");
                    if (error) {
                        adapter.notifyDataSetChanged();
                        txtStatusBox.setText("");
                        imgImageUpload.setImageBitmap(null);
                        imgImageUpload.setBackgroundResource(R.drawable.image);
                        Toast.makeText(TimelineActivity.this, message, Toast.LENGTH_SHORT).show();
                        slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);

                    } else {

                        // Error occurred in registration. Get the error
                        // message
                        String errorMsg = jObj.getString("message");
                        Toast.makeText(TimelineActivity.this, errorMsg, Toast.LENGTH_LONG).show();
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                Toast.makeText(TimelineActivity.this, "Oops something went wrong...", Toast.LENGTH_LONG).show();
                hideDialog();
            }
        }) {

            @Override
            protected Map<String
                    , String> getParams() {
                // Posting params to register url
                Map<String, String> params = new HashMap<String, String>();
                params.put("my_token", token);
                params.put("story_text", story_text);
                params.put("image", image);

                return params;
            }

        };

        // Adding request to request queue
        AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
    }

Solution

  • You need to implement some sort of polling mechanism on server end to do this. There's a workaround for it but it's not considered good practice. You can use a Timer to call your getTimeline function periodically to update the recycler view. Something like this in your onCreate:

    Timer autoRefresh;
    autoRefresh=new Timer();
        autoRefresh.schedule(new TimerTask() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    public void run() {
                        getTimeLineData(token, page);
                    }
                });
            }
        }, 0, your_time_in_milliseconds);
    

    You can even do this asynchronously by using AsyncTask in Android.