2

I have a recycler view using a custom adapter. I have a button on the custom adapter to delete a row from the database when clicked. This works fine but I now want the view to update from the server and present the user with the row they deleted gone. The code I will post below does not give any errors but does not refresh properly. I will attach my class and also the adapter too. Thanks.

MyReviews.Java

public class MyReviews extends AppCompatActivity {
    private ArrayList reviewername;
    private ArrayList reviewscore;
    private ArrayList reviewerpic;
    private ArrayList reviewdate;
    private ArrayList reviewtext;
    private ArrayList reviewid;
    private static String url;
    private String TAG = SearchScreen.class.getSimpleName();
    private ProgressDialog pDialog;
    private String userid;

    SessionManagement session;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        reviewername = new ArrayList<>();
        reviewscore = new ArrayList<>();
        reviewerpic = new ArrayList<>();
        reviewdate = new ArrayList<>();
        reviewtext = new ArrayList<>();
        reviewid = new ArrayList<>();
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_reviews);
        setTitle("My Reviews");
        session = new SessionManagement(getApplicationContext());
        HashMap<String, String> user = session.getUserDetails();
        userid = user.get(SessionManagement.KEY_ID);
        url = "url" + userid;
        Log.d("URL", url);
        initViews();
    }

    private void initViews() {
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.myreviewslist);
        recyclerView.setHasFixedSize(true);
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(layoutManager);
        new GetMyReviews().execute();
    }

    private class GetMyReviews extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            // Showing progress dialog
            pDialog = new ProgressDialog(MyReviews.this);
            pDialog.setMessage("Please Wait..");
            pDialog.setCancelable(false);
            pDialog.show();

        }

        @Override
        protected Void doInBackground(Void... arg0) {
            HttpHandler sh = new HttpHandler();

            // Making a request to url and getting response
            String jsonStr = sh.makeServiceCall(url);

            Log.e(TAG, "Response from url: " + jsonStr);

            if (jsonStr != null) {
                try {
                    JSONObject jsonObj = new JSONObject(jsonStr);

                    // Getting JSON Array node
                    JSONArray contacts = jsonObj.getJSONArray("MyGeek");

                    // looping through All Contacts
                    for (int i = 0; i < contacts.length(); i++) {
                        JSONObject c = contacts.getJSONObject(i);

                        reviewername.add(c.getString("reviewername"));
                        reviewscore.add(c.getString("reviewscore"));
                        reviewerpic.add(c.getString("reviewerpic"));
                        reviewdate.add(c.getString("reviewdate"));
                        reviewtext.add(c.getString("reviewtext"));
                        reviewid.add(c.getString("reviewid"));


                    }
                } catch (final JSONException e) {
                    Log.e(TAG, "Json parsing error: " + e.getMessage());
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(getApplicationContext(),
                                    "Json parsing error: " + e.getMessage(),
                                    Toast.LENGTH_LONG)
                                    .show();
                        }
                    });

                }
            } else {
                Log.e(TAG, "Couldn't get json from server.");
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getApplicationContext(),
                                "Couldn't get json from server. Check LogCat for possible errors!",
                                Toast.LENGTH_LONG)
                                .show();
                    }
                });

            }

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            pDialog.hide();

            RecyclerView recyclerView = (RecyclerView) findViewById(R.id.myreviewslist);

            RecyclerView.Adapter adapter = new DataAdapterMyReviews(reviewername, reviewscore, reviewerpic, reviewdate, reviewtext, reviewid);
            recyclerView.setAdapter(adapter);


        }
    }
}

DataAdapterMyReviews.Java

public class DataAdapterMyReviews extends RecyclerView.Adapter<DataAdapterMyReviews.ViewHolder> {
    private ArrayList<String> reviewername;
    private ArrayList<String> reviewscore;
    private ArrayList<String> reviewerpic;
    private ArrayList<String> reviewdate;
    private ArrayList<String> reviewtext;
    private ArrayList<String> reviewid;
    private static String url;
    private String TAG = SearchScreen.class.getSimpleName();
    private String success = "0";

    public DataAdapterMyReviews(ArrayList<String> reviewername, ArrayList<String> reviewscore, ArrayList<String> reviewerpic, ArrayList<String> reviewdate, ArrayList<String> reviewtext, ArrayList<String> reviewid) {
        this.reviewername = reviewername;
        this.reviewscore = reviewscore;
        this.reviewerpic = reviewerpic;
        this.reviewscore = reviewscore;
        this.reviewdate = reviewdate;
        this.reviewtext = reviewtext;
        this.reviewid = reviewid;

    }
    public void test(){
        this.notifyDataSetChanged();
    }

    @Override
    public DataAdapterMyReviews.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_row_reviews_withdelete, viewGroup, false);

        return new ViewHolder(view);

    }

    @Override
    public void onBindViewHolder(DataAdapterMyReviews.ViewHolder viewHolder, int i) {

        final int num;
        viewHolder.reviewnametext2.setText(reviewername.get(i));
        viewHolder.reviewscoretext2.setText(reviewscore.get(i));
        viewHolder.reviewtext2.setText(reviewtext.get(i));
        viewHolder.reviewdate2.setText(reviewdate.get(i));


        Picasso.with(viewHolder.itemView.getContext())
                .load(reviewerpic.get(i))
                .into(viewHolder.userpicreview2);
        num = i;
        viewHolder.delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("Delete ReviewID: ", reviewid.get(num));
                url = "url" + reviewid.get(num);
                new DeleteReview().execute();

            }
        });


        viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

            }
        });
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {
        private ImageView userpicreview2;
        private TextView reviewnametext2;
        private TextView reviewscoretext2;
        private TextView reviewtext2;
        private TextView reviewdate2;
        private Button delete;


        public ViewHolder(View view) {
            super(view);

            userpicreview2 = (ImageView) view.findViewById(R.id.userpicreview);
            reviewnametext2 = (TextView) view.findViewById(R.id.reviewnametext);
            reviewscoretext2 = (TextView) view.findViewById(R.id.reviewscoretext);
            reviewtext2 = (TextView) view.findViewById(R.id.reviewtext2);
            reviewdate2 = (TextView) view.findViewById(R.id.reviewdatetext);

            delete = (Button) view.findViewById(R.id.btnDeleteReview);


        }
    }

        private class DeleteReview extends AsyncTask<Void, Void, Void> {

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                // Showing progress dialog


            }

            @Override
            protected Void doInBackground(Void... arg0) {
                HttpHandler sh = new HttpHandler();

                // Making a request to url and getting response
                String jsonStr = sh.makeServiceCall(url);

                Log.e(TAG, "Response from url: " + jsonStr);

                if (jsonStr != null) {
                    try {
                        JSONObject jsonObj = new JSONObject(jsonStr);

                        // Getting JSON Array node
                        JSONArray contacts = jsonObj.getJSONArray("MyGeek");

                        // looping through All Contacts

                            JSONObject c = contacts.getJSONObject(0);

                           success = c.getString("success");




                    } catch (final JSONException e) {
                        Log.e(TAG, "Json parsing error: " + e.getMessage());



                    }
                } else {
                    Log.e(TAG, "Couldn't get json from server.");

                }

                return null;
            }

            @Override
            protected void onPostExecute(Void result) {
                super.onPostExecute(result);

                if(success.equals("1")){

                    Log.d("reviewdelete","success");
                    test();


                }
                else if(success.equals("0")){
                    Log.d("reviewdelete","fail");

                }
            }
        }
    }
Curtis Boylan
  • 737
  • 1
  • 6
  • 21

3 Answers3

0

You need to notify your activity about the dataset change. key point is to call notifyDataSetChanged() of adapter object. You should modify your current Activity class to have the reference of the adapter. Better you put adapter codes in a function in activity class then call in from the inner class.

Create a interface,

public interface DataListener {
    void deleteSuccess();
    void deleteError();
}

Assign listener to be notified,

public class MyReviews extends AppCompatActivity implements DataListener {
...your codes
//you need to implement the interface methods

@Override
public void deleteSuccess(){
  adapter.notifyDataSetChanged();
  Toast.makeText(this, "Successfully deleted",Toast.LENGTH_LONG).show();
}

@Override
public void deleteError(){
  Toast.makeText(this, "Failed to delete",Toast.LENGTH_LONG).show();
}


}

Notify listener,

private class DeleteReview extends AsyncTask<Void, Void, Void> {
....your code...

    @Override
    protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            if(success.equals("1")){

                //get the databaseListener object from your Adapter class constructor.

                databaseListener.deleteSuccess();


            }
            else if(success.equals("0")){
                databaseListener.deleteError();

            }
        }
Sadiq Md Asif
  • 847
  • 6
  • 18
0

Try this: inside yours DeleteReview.onPostExecute() first call List.remove(int index) to remove the item from the data lists. Afterwards call notifyItemRemoved to refresh recyclerView.

Pitt90
  • 31
  • 3
0

I recommend these changes:

  1. In ViewHolder ClickListener change this: new DeleteReview(i).execute(); //i is the position of row
  2. Add a variable to your ASyncTask class to hold position of deleted row
  3. In PostExecute: DataAdapterMyReviews.this.notifyItemRemoved(i); //Position of Deleted Row

Btw as long as your dataset is not changed, calling notify wont result in any change in View so be sure to change your dataset after database is changed. For example after delete operation be sure to do this:

reviewername.remove(i);
reviewscore.remove(i);
reviewerpic.remove(i);
reviewdate.remove(i);
reviewtext.remove(i);
reviewid.remove(i);

As long as Adapter is concerned the above variables are your model.. change in reviewername size directly result in change in RecyclerView cell size.. So as long as these variables are unchanged calling notify won't change anything..

Keivan Esbati
  • 2,855
  • 1
  • 17
  • 35