Search code examples
androidsimplecursoradapterandroid-cursoradaptertimeline

Contantly updating textview in a custom cursor adapter


I have a

  1. TimelineViewActivity class, contains a listView
  2. TimelineFeedsCursorAdapter class, extends the CursorAdapter

Here, in this adapter class I am fetching the rows from SQLite db and populating the list.

Now in each list item there is a time specifying when was the timeline feed created i.e. 2 hours ago or 10 hours ago, etc.

How can I update the time TextView constantly using a Handler and postDelay() function from TimelineViewActivity class so that I don't have to refresh each item all the time, just like in Facebook app - the timeline posts.


Solution

  • You shouldn't use Handler. When using CursorAdapter with db integration best thing to do is to implements LoaderCallbacks<Cursor> which will give you callback on every database changes. you will need to initiate the callback on your onCreate method like this: getLoaderManager().initLoader(0, null, this);

    Now the fun part: when implementing LoaderCallbacks<Cursor> you will forced to override three methods:

    first method will be called once and create the loader. when creating the loader, you specifying which columns you want to receive on each database change:

            @Override
        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
            CursorLoader loader = new CursorLoader(getActivity(), DataProvider.CONTENT_URI_MESSAGES, new String[] {
                    DataProvider.COL_ID, DataProvider.COL_NAME, DataProvider.COL_DATE }, null, null, DataProvider.COL_DATE
                    + " DESC");
            return loader;
        }
    

    second method will be called when the loader will created and on every database change on the loader table (I think this is what you looking for):

            @Override
        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
            Log.i("");
            adapter.swapCursor(data);
        }
    

    the last methode will be called when the loader rest itself:

            @Override
        public void onLoaderReset(Loader<Cursor> loader) {
            adapter.swapCursor(null);
        }
    

    Visit http://developer.android.com/guide/components/loaders.html for more information.

    EDIT: try use the code from within your adapter:

    @Override
            public void setViewText(TextView textView, String text) {
    
                if(textView.getId() == R.id.tv_time_past) {
                     long creation_date = 0;
                     if (text.matches("[0-9]+") && text.length() > 2)                   
                         creation_date = Long.parseLong();
                     if(creation_date > 0)
                         new DateSetter(textView, creation_date );
    
                }
    }
    

    code for DateSetter thread:

       private class DateSetter extends Thread{
    
        private TextView textView;
        private long creation_date;
    
        public DateSetter(TextView textView, long creation_date){
            this.textView = textView;
            this.creation_date = creation_date;
        }
    
        @Override
        public synchronized void run() {
            while (mRunning) {
                String datePast = getTimePastAsString(System.currentTimeMillis(), creation_date);
                Long.parseLong()
                textView.setText(datePast);
                try {
                    Thread.sleep(1000);// update every 1 seconds
                } catch(Exception e){};
            }
        }
    }