0

I'm quite new to android (I'm a newb, I know :/) and am wondering how to proceed. I am writing an app that takes data from a server, saves it to a SQLite table and displays it in a list. The thing is, I don't know how I should update the listview when data is refreshed from the server. Right now I am just resetting the adapter each time, but surely there is a more efficient method. I've read lots on notifydatasetchanged() but I'm still not sure how to use it. Any ideas?

ListAdapter:

private class MyListAdapter extends ArrayAdapter<Plants> {
    private final LayoutInflater mInflater;
    ItemInfo info = new ItemInfo();

    public MyListAdapter(Context c) {
        super(c, R.layout.list_item, myPlants);
        mInflater = (LayoutInflater) getActivity().getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);
    }

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

        View itemView;
        if (convertView == null) {
            itemView = mInflater.inflate(R.layout.list_item, parent, false);
        } else {
            itemView = convertView;
        }
        // Find the Plant to work with.
        Plant currentPlant = myPlants.get(position);

        // Plant number:
        TextView plantText = (TextView) itemView
                .findViewById(R.id.plantID);
        plantText .setText("Plant: " + currentPlant .getPlantID());

        // Information string:
        TextView infoText = (TextView) itemView.findViewById(R.id.state);
        infoText.setText("Status: "
                + info.getStatus(currentPlant.getState()) + " at "
                + info.getLocation(currentPlant.getLocation()));

        // Grey out checked out plants
        if (currentPlant.getState().equals("3")) {
            itemView.setBackgroundColor(Color.LTGRAY);
        }

        return itemView;
    }
}

This method is what I am calling to update the list right now:

private List<Plant> myPlants = new ArrayList<Plant>();
public void updateList() {
    // Get everything back from database
    try {
        SQLHelper getHelper = new SQLHelper(getActivity());
        getHelper.open();
        myPlants = getHelper.getData();
        getHelper.close();
    } catch (Exception e) {
        iError = 2;
    }
    // Updating database data into ListVIew
    if (myPlants != null) {
        ArrayAdapter<Package> adapter = new MyListAdapter(getActivity());
        setListAdapter(adapter);
    }
}

I'm all out of ideas right now... Thanks!

  • Whenever you are updating(adding/deleting objects) the backing arraylist for adapter,just call adapter.notifydatasetchanged(on UI thread). – nikhil.thakkar Mar 17 '14 at 07:30
  • Oh wow, it's that easy? Does it replace or append the list? –  Mar 17 '14 at 07:30
  • When you add, it just appends to the arraylist. – nikhil.thakkar Mar 17 '14 at 07:32
  • Doesn't seem to want to work, I moved `adapter = new MyListAdapter(getActivity()); setListAdapter(adapter);` to onCreate and `adapter.notifyDataSetChanged();` in the `updateList()` bit after `getHelper.close();` –  Mar 17 '14 at 07:42
  • Don't create another object for the adapter, create it only once and then call the notifydatasetchanged method. – nikhil.thakkar Mar 17 '14 at 07:44

3 Answers3

0

For example You have a listView opened and by long click on item You can remove it so to see changes immediately You should use notifyDataSetChanged(). It works when Your list is updated.

RobertoB
  • 13
  • 9
0

Adapter maintains a reference to the same list which you specified when you defined
In your adapter constructor its myPlants

super(c, R.layout.list_item, myPlants);

When you get new list of items do not create a new list and assign.
Instead you copy the items from the new list to the myPlants and call notifyDataSetChanged() on the adapter

List<Plant> newList = null;
    try {
                  SQLHelper getHelper = new SQLHelper(getActivity());
                  getHelper.open();
                  newList = getHelper.getData();
                  getHelper.close();
                } 
                catch (Exception e) {
               iError = 2;
                }
    if (newList != null)
           {        myPlants.clear();
        myPlants.addAll(newList);

            runOnUiThread(new Runnable()
                {
              @Override
                  public void run()
              {
               adapter.notifyDataSetChanged();
              }
            });
           }
BlackBeard
  • 145
  • 6
  • INFO: notifyDataSetChanged() should be called in ui thread, as the list has to update the view. Also use the runonuithread() as a separate refresh() method which will be very useful – BlackBeard Mar 17 '14 at 08:29
0

Have a look at this Question & Answer. Here some details will help you to understand the use of notifydatasetchanged(). Also there is a video link shared on the Answer which is the most helpful. And obviously notifydatasetchanged() is the best way rather than custom refresh. Also this one.

When ever you get the latest data from server/database, you just need to call notifydatasetchanged(), a very bad practice will be to create a new adapter every time. Hope you have an event based functionality, such as "refresh button" or "scroll down to refresh", to get the event on which you have to refresh the view.

Your getView should be modify by this

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

    View itemView;
    if (convertView == null) {
        itemView = mInflater.inflate(R.layout.list_item, parent, false);
    } else {
        itemView = convertView;
    }
    // Find the Plant to work with.
    Plant currentPlant = myPlants.get(position);



    if(itemView!=null){
    // Plant number:
    TextView plantText = (TextView) itemView
            .findViewById(R.id.plantID);
    plantText .setText("Plant: " + currentPlant .getPlantID());

    // Information string:
    TextView infoText = (TextView) itemView.findViewById(R.id.state);
    infoText.setText("Status: "
            + info.getStatus(currentPlant.getState()) + " at "
            + info.getLocation(currentPlant.getLocation()));
    }



    // Grey out checked out plants
    if (currentPlant.getState().equals("3")) {
        itemView.setBackgroundColor(Color.LTGRAY);
    }

    return itemView;
}
Community
  • 1
  • 1
Shad
  • 1,587
  • 2
  • 20
  • 29
  • thanks! On another note, when I press the refresh button, it starts getting new info from the server and saving in a asynctask. The asynctask then calls updateList(); on post execute. Weird things is, when I tap the refresh button and then press a list item, I get a FC with indexoutofboundsexception exception. Any ideas? I don't want to ask another question as it's not a major issue. –  Mar 17 '14 at 08:08