0

I have a list view containing few fields coming from back end. One feed is 'number of likes'. When I click on any list row it opens one activity for that row, there like button in that activity. When user presses like it get appended on server. Now the problem is it should show incremented value in the list view when user go back to list view activity. How to do that?

NOTE: Like counter is incremented if I close the app and start it again. I tried to call on Create method again from on Resume method but it produces duplicate copy of rows every time list view activity is remusmed.

Here is my list activity code.

public class MainActivity extends Activity {


// Session Manager Class
SessionManager session;

// Log tag
private static final String TAG = MainActivity.class.getSimpleName();

// Movies json url
private static final String url = "MY_URL";
private ProgressDialog pDialog;
private List<Movie> movieList = new ArrayList<Movie>();
private ListView listView;


private CustomListAdapter adapter;
{

    // Creating volley request obj
    JsonArrayRequest movieReq = new JsonArrayRequest(url,
            new Response.Listener<JSONArray>() {
                @Override
                public void onResponse(JSONArray response) {
                    Log.d(TAG, response.toString());
                    hidePDialog();

                    // Parsing json
                    for (int i = 0; i < response.length(); i++) {
                        try {

                            JSONObject obj = response.getJSONObject(i);
                            Movie movie = new Movie();
                            movie.setThumbnailUrl(obj.getString("image"));
                            movie.setTitle(obj.getString("title"));
                            movie.setDate(obj.getString("date"));
                            movie.setVideo(obj.getString("video"));
                            movie.setLikes(obj.getInt("likes"));
                            movie.setId(obj.getInt("id"));

           // adding movie to movies array
                            movieList.add(movie);



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


                    }

                    // notifying list adapter about data changes
                    // so that it renders the list view with updated data

                    adapter.notifyDataSetChanged();
                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            VolleyLog.d(TAG, "Error: " + error.getMessage());
            hidePDialog();

        }
    });

    // Adding request to request queue
    AppController.getInstance().addToRequestQueue(movieReq);
}



@Override
protected void onCreate(Bundle savedInstanceState) {


    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);


    //creating unique ID
    final String deviceId = Settings.Secure.getString(this.getContentResolver(),
            Settings.Secure.ANDROID_ID);
    Toast.makeText(this, deviceId, Toast.LENGTH_SHORT).show();

    Toast.makeText(getApplicationContext(), "User Login Status: " + session.isLoggedIn(), Toast.LENGTH_LONG).show();
    /**
     * Call this function whenever you want to check user login
     * This will redirect user to LoginActivity is he is not
     * logged in
     * */
    session.checkLogin();


    listView = (ListView) findViewById(R.id.list);
    adapter = new CustomListAdapter(this, movieList);
    listView.setAdapter(adapter);
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                                        @Override
                                        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                                            // getting values from selected ListItem


                                          //  ImageView thumbNail = (ImageView)view.findViewById(R.id.thumbnail);
                                            String title = ((TextView) view.findViewById(R.id.title)).getText().toString();

                                            String likes = ((TextView)view.findViewById(R.id.likes)).getText().toString();
                                           String date = ((TextView)view.findViewById(R.id.date)).getText().toString();
                                            String video = ((TextView) view.findViewById(R.id.video)).getText().toString();
                                            String idd = ((TextView) view.findViewById(R.id.idd)).getText().toString();


                                            // Starting single contact activity
                                            Intent in = new Intent(getApplicationContext(), MovieDetailActivity.class);
                                           //  in.putExtra("THUMB", thumbNail.toString());
                                            in.putExtra("TITLE", title);
                                            in.putExtra("LIKES", likes);
                                              in.putExtra("DATE", date);
                                            in.putExtra("VIDEO", video);
                                             in.putExtra("IDD", idd);
                                            in.putExtra("UNIQUEID",deviceId);


                                            //in.putExtra(TAG_URL,"url");
                                            // in.putExtra(TAG_PHONE_MOBILE, description);
                                            startActivity(in);

                                        }

                                    }

    );




    // Creating volley request obj
enter code here
    JsonArrayRequest movieReq = new JsonArrayRequest(url,
            new Response.Listener<JSONArray>() {
                @Override
                public void onResponse(JSONArray response) {
                    Log.d(TAG, response.toString());
                    hidePDialog();

                    // Parsing json
                    for (int i = 0; i < response.length(); i++) {
                        try {

                            JSONObject obj = response.getJSONObject(i);
                            Movie movie = new Movie();
                            movie.setThumbnailUrl(obj.getString("image"));
                            movie.setTitle(obj.getString("title"));
                            movie.setDate(obj.getString("date"));
                            movie.setVideo(obj.getString("video"));
                            movie.setLikes(obj.getInt("likes"));
                            movie.setId(obj.getInt("id"));

                            // adding movie to movies array
                            movieList.add(movie);

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


                    }

                    // notifying list adapter about data changes
                    // so that it renders the list view with updated data

                    adapter.notifyDataSetChanged();
                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            VolleyLog.d(TAG, "Error: " + error.getMessage());
            hidePDialog();

        }
    });

    // Adding request to request queue
    AppController.getInstance().addToRequestQueue(movieReq);
}

@Override
protected void onResume() {
    super.onResume();


}

@Override
public void onDestroy() {
    super.onDestroy();
    hidePDialog();
}

private void hidePDialog() {
    if (pDialog != null) {
        pDialog.dismiss();
        pDialog = null;
    }
}




@Override
 public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

public class CustomListAdapter extends BaseAdapter {
    private Activity activity;
    private LayoutInflater inflater;
    private List<Movie> movieItems;
    ImageLoader imageLoader = AppController.getInstance().getImageLoader();

    public CustomListAdapter(Activity activity, List<Movie> movieItems) {
        this.activity = activity;
        this.movieItems = movieItems;
    }

    @Override
    public int getCount() {
        return movieItems.size();
    }

    @Override
    public Object getItem(int location) {
        return movieItems.get(location);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }



    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        if (inflater == null)
            inflater = (LayoutInflater) activity
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (convertView == null)
            convertView = inflater.inflate(R.layout.list_row, null);

        if (imageLoader == null)
            imageLoader = AppController.getInstance().getImageLoader();
        NetworkImageView thumbNail = (NetworkImageView) convertView
                .findViewById(R.id.thumbnail);
        TextView title = (TextView) convertView.findViewById(R.id.title);
        TextView likes = (TextView) convertView.findViewById(R.id.likes);
        TextView date = (TextView) convertView.findViewById(R.id.date);
        TextView video = (TextView) convertView.findViewById(R.id.video);
        TextView id = (TextView) convertView.findViewById(R.id.idd);
        //TextView year = (TextView) convertView.findViewById(R.id.releaseYear);

        // getting movie data for the row
        Movie m = movieItems.get(position);

        // thumbnail image
        thumbNail.setImageUrl(m.getThumbnailUrl(), imageLoader);

        // title
        title.setText(m.getTitle());

        // rating
        date.setText(m.getDate());
        video.setText(m.getVideo());

        likes.setText(String.valueOf(m.getLikes()));
        id.setText(String.valueOf(m.getId()));


        return convertView;
        // Listview on item click listener

    }

    @Override
    public void notifyDataSetChanged() {
        super.notifyDataSetChanged();
    }
}
justcurious
  • 839
  • 3
  • 12
  • 29
Shelby
  • 81
  • 1
  • 11
  • After changing the data set, call adapter.notifyDataSetChanged(); also make sure it is calling from the main thread – Jackson Chengalai Oct 20 '15 at 11:27
  • This isn't an answer but a suggestion. Would you be opposed to using a RecyclerView and a SortedList? If not, this will automatically update the RecyclerView with updated data when you retrieve the data again and apply it to the RecyclerView. It also prevents duplicates. Let me know if you have interest and I'll post it. – AnxGotta Oct 20 '15 at 11:29
  • please post @AnxGotta – Shelby Oct 21 '15 at 04:45

1 Answers1

0

Requested implementation using a SortedList and RecyclerView:

Here is the example I used to build mine.

This is my slightly more complex code that includes sorting via a SearchView in the toolbar. You can use the example in the above link if you want the example without the sorting. The control logic is in my Presenter class that manages this adapter and the Fragment:

public class AdapterInstitutionList extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

// lists to control all items and items visible after sorting
private SortedList<MInstitutionInfo> visibleList;
private ArrayList<MInstitutionInfo> allItems;

// my fragment and the presenter
private FInstitutionSelection fInstitutionSelection;
private PInstitutionList presenter;


public AdapterInstitutionList(PInstitutionList pInstitutionSelection, FInstitutionSelection fInstitutionSelection) {
    // get ref to fragment, presenter, and create new callback for sortedlist
    this.fInstitutionSelection = fInstitutionSelection;
    presenter = pInstitutionSelection;
    visibleList = new SortedList<>(MInstitutionInfo.class, new InstitutionListCallback());
    allItems = new ArrayList<>();

}

// inflate your list item view here
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.listitem_institution, parent, false);
    return new InstitutionViewHolder(view);
}

// on binding, you populate your list item with the values, onclickhandle, etc
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
    InstitutionViewHolder institutionViewHolder = (InstitutionViewHolder) viewHolder;
    final MInstitutionInfo institutionInfo = visibleList.get(position);
    institutionViewHolder.setInstitutionInfo(institutionInfo);
    institutionViewHolder.populateTextView();
    institutionViewHolder.parent.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            presenter.onInstitutionSelected(institutionInfo);
        }
    });
}


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

// my utility function for the presenter/fragment
public MInstitutionInfo get(int position) {
    return visibleList.get(position);
}

public int add(MInstitutionInfo item) {
    return visibleList.add(item);
}

public int indexOf(MInstitutionInfo item) {
    return visibleList.indexOf(item);
}

public void updateItemAt(int index, MInstitutionInfo item) {
    visibleList.updateItemAt(index, item);
}

public void addAll(List<MInstitutionInfo> items) {
    visibleList.beginBatchedUpdates();
    try {
        for (MInstitutionInfo item : items) {
            visibleList.add(item);
            allItems.add(item);
        }
    } finally {
        visibleList.endBatchedUpdates();
    }
}

public void addAll(MInstitutionInfo[] items) {
    addAll(Arrays.asList(items));
}

public boolean remove(MInstitutionInfo item) {
    return visibleList.remove(item);
}

public MInstitutionInfo removeItemAt(int index) {
    return visibleList.removeItemAt(index);
}

public void clearVisibleList() {
    visibleList.beginBatchedUpdates();
    try {
        // remove items at end to remove unnecessary array shifting
        while (visibleList.size() > 0) {
            visibleList.removeItemAt(visibleList.size() - 1);
        }
    } finally {
        visibleList.endBatchedUpdates();
    }
}

public void clearAllItemsList() {
    allItems.clear();
}

public void filterList(String queryText) {
    clearVisibleList();
    visibleList.beginBatchedUpdates();
    try {
        String constraint = queryText.toLowerCase();
        for (MInstitutionInfo institutionInfo : allItems) {
            if (institutionInfo.getName() != null && institutionInfo.getName().toLowerCase().contains(constraint)) {
                visibleList.add(institutionInfo);
            }
        }
    } finally {
        visibleList.endBatchedUpdates();
    }
}

public void clearFilter() {
    if (visibleList.size() == allItems.size()) {
        return;
    }
    clearVisibleList();
    visibleList.beginBatchedUpdates();
    try {
        for (MInstitutionInfo institutionInfo : allItems) {
            visibleList.add(institutionInfo);
        }
    } finally {
        visibleList.endBatchedUpdates();
    }
}

// the callback for the SortedList
// this manages the way in which items are added/removed/changed/etc
// mine is pretty simple
private class InstitutionListCallback extends SortedList.Callback<MInstitutionInfo> {
    @Override
    public int compare(MInstitutionInfo o1, MInstitutionInfo o2) {
        return o1.getName().compareTo(o2.getName());
    }

    @Override
    public void onInserted(int position, int count) {
        notifyItemRangeInserted(position, count);
    }

    @Override
    public void onRemoved(int position, int count) {
        notifyItemRangeRemoved(position, count);
    }

    @Override
    public void onMoved(int fromPosition, int toPosition) {
        notifyItemMoved(fromPosition, toPosition);
    }

    @Override
    public void onChanged(int position, int count) {
        notifyItemRangeChanged(position, count);
    }

    @Override
    public boolean areContentsTheSame(MInstitutionInfo oldItem, MInstitutionInfo newItem) {
        return oldItem.getName().equals(newItem.getName());
    }

    @Override
    public boolean areItemsTheSame(MInstitutionInfo item1, MInstitutionInfo item2) {
        return item1.getName().equals(item2.getName());
    }
}

// this is the view holder that is used for the list items
private class InstitutionViewHolder extends RecyclerView.ViewHolder {

    public View parent;
    public TextView tvName;
    public MInstitutionInfo institutionInfo;

    public InstitutionViewHolder(View itemView) {
        super(itemView);
        parent = itemView;
        tvName = (TextView) itemView.findViewById(R.id.tv_institution_listitem_name);
    }

    public MInstitutionInfo getInstitutionInfo() {
        return institutionInfo;
    }

    public void setInstitutionInfo(MInstitutionInfo institutionInfo) {
        this.institutionInfo = institutionInfo;
    }

    public void populateTextView() {
        if (tvName != null && institutionInfo != null && institutionInfo.getName() != null) {
            tvName.setText(institutionInfo.getName());
        }
    }

}

You simply instantiate this adapter and assign it to your RecyclerView

myRecyclerView.setAdapter(myAdapter);

When you call any of the batched updates, the list will automatically update itself in the UI. So when you get your initial data, just call addAll(yourData) and the RecyclerView will auto populate the list. When you get updated data, you just call addAll(yourNewData) and the RecyclerView will automatically add new items and remove the new non-existent items leaving you with a fully updated list. You will need to be sure to implement the SorteList.Callback methods compare(...), areContentsTheSame(...), areItemsTheSame(...) properly to ensure that this behaves as you want it to when adding/removing items.

Please let me know if you need any more help. Frankly, this implementation type for updated and sorted data is extremely smooth.

Community
  • 1
  • 1
AnxGotta
  • 1,006
  • 7
  • 28