0

In my code, I want to update ListView periodically say after every 10 seconds. As ListView is custom and data in ListView are populated from database, I need to refresh ListView periodically so that any changes in database can be reflected in ListView. I tried using Handler concept but it didn't help me. Below is my code. What needs to be done?

 public class GetFriendDeviceId extends ListActivity {

        String data = "";

        String title;


        ListView list;
        CustomDeviceId adapter;
        ArrayList<String> useridarr;
        ArrayList<String> namearr;
        ArrayList<String> regidarr;

        ArrayList<String> statusarr;
        String id;

        String userid, name, regid;

        private static final String USERID = "user_id";
        private static final String NAME = "user_name";
        private static final String REGID = "regId";

        DBController contoller = new DBController(this);

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.getfriend_deviceid);

            useridarr = new ArrayList<String>();
            namearr = new ArrayList<String>();
            regidarr = new ArrayList<String>();
            statusarr = new ArrayList<String>();

            // get user_id using sharedpreference
            SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
            id = preferences.getString("ID", "");

            new GetContent().execute();

        }

        // asynctask to get content for selected title
        public class GetContent extends AsyncTask<Void, Void, Void>
        {
             ProgressDialog pdLoading = new ProgressDialog(GetFriendDeviceId.this);

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

                    useridarr.clear();
                namearr.clear();
                regidarr.clear();
                statusarr.clear();

                pdLoading.setMessage("\tPlease wait...");
            pdLoading.show();
            }

            @Override
            protected Void doInBackground(Void... params) {
                final GetDeviceId getdb = new GetDeviceId();
                new Thread(new Runnable() {
                    public void run() {
                        data = getdb.getDataFromDB(id);
                        System.out.println(data);

                        runOnUiThread(new Runnable() {

                            @Override
                            public void run() {
                                ArrayList<User_DeviceId> users = parseJSON(data);
                                addData(users);                     
                            }
                        });

                    }
                }).start();

                return null;

            }

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

                pdLoading.dismiss();

            }
        }



        public ArrayList<User_DeviceId> parseJSON(String result) {
            ArrayList<User_DeviceId> users = new ArrayList<User_DeviceId>();

            try
            {
                JSONArray jArray = new JSONArray(result);

                for (int i = 0; i < jArray.length(); i++) 
                {
                    JSONObject json_data = jArray.getJSONObject(i);
                    User_DeviceId user = new User_DeviceId();

                    user.setUser_id(json_data.getString(USERID));
                    user.setUser_name(json_data.getString(NAME));
                    user.setRegId(json_data.getString(REGID));
                    users.add(user);

                }


            } catch (JSONException e) {
                Log.e("log_tag", "Error parsing data " + e.toString());  
            }
            return users;
        }


        @SuppressWarnings({ "rawtypes" })
        public void addData(ArrayList<User_DeviceId> users) {

            for (Iterator i = users.iterator(); i.hasNext();) {

                User_DeviceId p = (User_DeviceId) i.next();

                useridarr.add(p.getUser_id());
                namearr.add(p.getUser_name());
                regidarr.add(p.getRegId());

            }


            DBController.statusArray = statusarr;
        contoller.getStatus(id, useridarr, 0);

            adapter = new CustomDeviceId(GetFriendDeviceId.this, namearr, useridarr, statusarr);
            list.setAdapter(adapter);

        }

I tried this code

final Handler handler_new = new Handler();
        handler_new.postDelayed( new Runnable() {
        @Override
            public void run() {

                DBController.statusArray = MainActivity.result;
                contoller.Status("100003818200590", "100007144268382", 0);
                MainActivity.adapter.notifyDataSetChanged();
                handler_new.postDelayed( this, 1000);

            }
        }, 1000);

But didn't work...

Sahil Mahajan Mj
  • 11,033
  • 8
  • 53
  • 100
Looking Forward
  • 3,579
  • 8
  • 45
  • 65
  • postDelayed(runnable, yourtime);, see this as a reference http://stackoverflow.com/questions/10845172/android-running-a-method-periodically-using-postdelayed-call – Triode Feb 17 '14 at 10:08
  • @RajeshCP: I edited my question, have a look at it – Looking Forward Feb 17 '14 at 10:10
  • and call NotifyDataSetChanged() when you update your data, new a adapter every time is unnecessary – bladefury Feb 17 '14 at 10:11
  • NotifyDataSetChanged() tells the listview to invalidate the views; the adapter still needs to find the new data to repopulate the views, or its just going to use old data. Don't see any adapter code to know if that's happening or not. – NameSpace Feb 17 '14 at 10:19

3 Answers3

2

I just Edit your code hope this helps you

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.ListView;

public class GetFriendDeviceId extends ListActivity {

    String data = "";

    String title;

    ListView list;
    CustomDeviceId adapter;
    ArrayList<String> useridarr;
    ArrayList<String> namearr;
    ArrayList<String> regidarr;

    ArrayList<String> statusarr;
    String id;

    String userid, name, regid;

    private static final String USERID = "user_id";
    private static final String NAME = "user_name";
    private static final String REGID = "regId";

    DBController contoller;

    Timer timer;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.getfriend_deviceid);
        contoller = new DBController(this);
        useridarr = new ArrayList<String>();
        namearr = new ArrayList<String>();
        regidarr = new ArrayList<String>();
        statusarr = new ArrayList<String>();

        // get user_id using sharedpreference
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
        id = preferences.getString("ID", "");

        timer = new Timer();

        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        new GetContent().execute();
                    }
                });

            }
        }, 0, 10000);

    }

    // asynctask to get content for selected title
    public class GetContent extends AsyncTask<Void, Void, ArrayList<User_DeviceId>> {
        ProgressDialog pdLoading = new ProgressDialog(GetFriendDeviceId.this);

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            useridarr.clear();
            namearr.clear();
            regidarr.clear();
            statusarr.clear();
            pdLoading.setMessage("\tPlease wait...");
            pdLoading.show();
        }

        @Override
        protected ArrayList<User_DeviceId> doInBackground(Void... params) {
            final GetDeviceId getdb = new GetDeviceId();
            data = getdb.getDataFromDB(id);
            ArrayList<User_DeviceId> users = parseJSON(data);

            return users;

        }

        @Override
        protected void onPostExecute(ArrayList<User_DeviceId> result) {
            super.onPostExecute(result);
            addData(result);
            pdLoading.dismiss();

        }
    }

    public ArrayList<User_DeviceId> parseJSON(String result) {
        ArrayList<User_DeviceId> users = new ArrayList<User_DeviceId>();

        try {
            JSONArray jArray = new JSONArray(result);

            for (int i = 0; i < jArray.length(); i++) {
                JSONObject json_data = jArray.getJSONObject(i);
                User_DeviceId user = new User_DeviceId();

                user.setUser_id(json_data.getString(USERID));
                user.setUser_name(json_data.getString(NAME));
                user.setRegId(json_data.getString(REGID));
                users.add(user);

            }

        } catch (JSONException e) {
            Log.e("log_tag", "Error parsing data " + e.toString());
        }
        return users;
    }

    @SuppressWarnings({ "rawtypes" })
    public void addData(ArrayList<User_DeviceId> users) {

        for (Iterator i = users.iterator(); i.hasNext();) {

            User_DeviceId p = (User_DeviceId) i.next();

            useridarr.add(p.getUser_id());
            namearr.add(p.getUser_name());
            regidarr.add(p.getRegId());

        }

        DBController.statusArray = statusarr;
        contoller.getStatus(id, useridarr, 0);

        adapter = new CustomDeviceId(GetFriendDeviceId.this, namearr, useridarr, statusarr);
        list.setAdapter(adapter);

    }
}
Biraj Zalavadia
  • 28,348
  • 10
  • 61
  • 77
  • why you want to use service? – Biraj Zalavadia Feb 17 '14 at 12:00
  • 1
    what I'm doing here is, when I receive push notification then and only then my listview should be updated. It will be a good practice to start service and update listview when I receive notification. and it will be better to update listview when notification received then updating it at every second – Looking Forward Feb 17 '14 at 12:03
  • Ok got your point. What you can do create a method say updaeList() in your list activity. And call that method when you receive notification. – Biraj Zalavadia Feb 17 '14 at 12:08
  • ok... and in that method, I should requery to database and notify adapter and call that method in service, and start this service when notification is received... am I ri8?? – Looking Forward Feb 17 '14 at 12:09
  • can u tell me about my logic, am I ri8?? (in previous to previous comment u can read) – Looking Forward Feb 18 '14 at 04:46
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/47718/discussion-between-biraj-zalavadia-and-anil-bhatiya) – Biraj Zalavadia Feb 18 '14 at 04:47
1

Constantly/Periodically polling for a change is not a good idea in general.

You should implement some thing like push notification when DB is updated for better performance. When a piece of code changes the content of DB, it should invoke all subscriber of listener/ or broadcast a message.

Your activity/fragment should implement that listener, and refresh the listview. This way your listview will be refreshed only when some changes occur in DB instead of looking for a change in DB and refresh itself.

A listview can be refreshed by modifying the backing datasource of listview.
namearr = newnamearr;
...

newnamearr is new contents for listview.

and then calling notifyDataSetChanged().

This piece of code is working but their could be better approach available. import java.util.ArrayList;

public class ListenerTest {
    public static void main(String[] args) {
        // simulation for activities.
        A a  = new A();
        a.simulateOnCreate();
        B b = new B();
        b.simulateOnCreate();

        DBChanger obj = new DBChanger();
        obj.changeDBContent();
    }
}

// this is class where all DB changes will occur.

class DBChanger{
    public void changeDBContent(){
        // some piece of Code that change the DB code.
        ArrayList<Listenable> subcribers = ListnerManager.getInstance().getSubscribersList();
        for(Listenable l: subcribers){
            l.onUpadateAvailable();
        }
    }
}

// This class should corresponds to Activity/Fragment in Android which will implement the listener

class A implements Listenable {


public void simulateOnCreate(){
    ListnerManager  maneger = ListnerManager.getInstance();
    maneger.setOnListenable(this);
}

@Override
public void onUpadateAvailable() {
    System.out.println("A---> onUpadateAvailable");

}

}

// This class is manager of listener.

class ListnerManager {
    public static ListnerManager instance = new ListnerManager();

    public static ListnerManager getInstance(){
        if(instance == null){
            instance = new ListnerManager();
        }
        return instance;
    }

    ArrayList<Listenable> subscriberlist = new ArrayList<Listenable>();

    public void setOnListenable(Listenable subcsriber) {
        subscriberlist.add(subcsriber);
    }

    public ArrayList<Listenable> getSubscribersList() {
        return subscriberlist;
    }
}

// Same as class A
class B implements Listenable {

    public void simulateOnCreate(){
        ListnerManager  maneger = ListnerManager.getInstance();
        maneger.setOnListenable(this);  
    }

    @Override
    public void onUpadateAvailable() {
        // TODO Auto-generated method stub
        System.out.println("B---> onUpadateAvailable");
    }   
}


interface Listenable {
    public void onUpadateAvailable();
}

Output i received on my console:

A---> onUpadateAvailable
B---> onUpadateAvailable
Gaurav Gupta
  • 4,586
  • 4
  • 39
  • 72
  • you said "When a piece of code changes the content of DB, it should invoke all subscriber of listener/ or broadcast a message"... how can I do that... any example??? – Looking Forward Feb 17 '14 at 10:24
0

I agree with @GauravGupta. The best way is to implement a push notification when there is changes in the database.

But regarding your problem you can try to run this asynctask:

class refreshList extends AsyncTask<String, String, String> {
     Context context

    public refreshList(Context context){
       this.context=context;



        @Override
        protected String doInBackground(String... params) {
            // TODO Auto-generated method sstub
            Timer timer = new Timer();
                  timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                // TODO Auto-generated method stub

//Since you cant invoke notify notifyDataSetChanged() inside the doInBackground. So we will use this code:
            ((MainActivity) context).runOnUiThread(new Runnable() {
                            public void run() {

                       //Do your code here like refreshing your adapter
                            MainActivity.adapter.notifyDataSetChanged();
                       //
                             }
                           });



            }
        }, 1000, 10000);
       //1000= interval delay;
       //10000= run every 10secs

            return null;
        }



    }

Remember to pass your activity's context when running the asynctask. new refreshList(this).execute();

icaneatclouds
  • 1,170
  • 9
  • 18