My Custom CursorAdapter doesn't update my ListView

时光毁灭记忆、已成空白 提交于 2019-12-23 05:17:35

问题


I'm having troubles with my Custom CursorAdapter and my ListView, the fact is, I can save data in my sqlite Database in my custom ContentProvider but my ListView is not populated.

I know DB Operations are heavy long operations, therefore I do it in another thread and furthermore CursorLoader is a subclass of AsyncTaskLoader, so it should be prepared for that.

With SimpleCursorAdapter works fine but with this Custom CursorAdapter not.

Can anyone tell me what is wrong and how could I solve it?

Thanks in advance.

My code is the following

public class TextNoteAdapter extends CursorAdapter {

    /*********** Declare Used Variables *********/

    private Cursor                 mCursor;
    private Context                mContext;         
    private static  LayoutInflater mInflater=null;

    /*************  TextNoteAdapter Constructor *****************/
    public TextNoteAdapter (Context context, Cursor cursor, int flags) {
        super(context, cursor,flags);

        mInflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mContext  = context;
        mCursor   = cursor;                           
    } 

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {

        //LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View view = mInflater.inflate(R.layout.textnote_info, parent, false);
        ViewHolder holder = new ViewHolder();

        holder.note_name               = (TextView)view.findViewById(R.id.note_name);
        holder.creation_date           = (TextView)view.findViewById(R.id.creation_date);
        holder.modification_date       = (TextView)view.findViewById(R.id.modification_date);
        holder.label_creation_date     = (TextView)view.findViewById(R.id.label_creation_date);
        holder.label_modification_date = (TextView)view.findViewById(R.id.label_modification_date);


        view.setTag(holder);

        return view;
    }    

     @Override
     public void bindView(View view, Context context, Cursor cursor) {
         // here we are setting our data what means, take the data from the cursor and put it in views
         View vi = view;
         ViewHolder holder = (ViewHolder)view.getTag();

         if(view==null){                  
             /****** Inflate textnote_info.xml file for each row ( Defined below ) *******/
             vi = mInflater.inflate(R.layout.textnote_info, null);

            /************  Set holder with LayoutInflater ************/
             vi.setTag( holder );

         } else 
             holder=(ViewHolder)vi.getTag();                          


         /************  Set Model values in Holder elements ***********/
         holder.note_name.setText(cursor.getString(cursor.getColumnIndex(TextNotesDb.KEY_NOTE_NAME)));
         holder.creation_date.setText(cursor.getString(cursor.getColumnIndex(TextNotesDb.KEY_CREATION_DATE)));
         holder.modification_date.setText(cursor.getString(cursor.getColumnIndex(TextNotesDb.KEY_MODIFICATION_DATE)));
         holder.label_creation_date.setText(Constants.LABEL_CREATION_DATE);
         holder.label_modification_date.setText(Constants.LABEL_MODIFICATION_DATE);

     }         


     @Override
     protected void onContentChanged() {
          // TODO Auto-generated method stub
          super.onContentChanged();
          notifyDataSetChanged();
     }         


     /********* Create a holder Class to contain inflated xml file elements *********/
     public static class ViewHolder{

         public TextView note_name;
         public TextView creation_date;
         public TextView modification_date;
         public TextView label_creation_date;
         public TextView label_modification_date;

     }



 }

And here my MainActivity

import android.app.Activity;
import android.app.LoaderManager;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends Activity implements LoaderManager.LoaderCallbacks<Cursor>{


    private Cursor              cursor;
    private Button              addButton;
    private ListView            listView;
    private TextNoteAdapter     dataAdapter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);     

        displayListView(); 

        addButton = (Button)findViewById(R.id.add_textnote);

        addButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // starts a new Intent to add a Note
                Intent intent = new Intent(getBaseContext(), TextNoteEdit.class);
                Bundle bundle = new Bundle();
                bundle.putString("mode", "add");
                intent.putExtras(bundle);
                startActivity(intent);
            }
        });

    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i("TAG", "MainActivity:: onResume");
        /** Starts a new or restarts an existing Loader in this manager **/
        getLoaderManager().restartLoader(0, null, this);
    }


    private void displayListView() {

    // That ensures a loader is initialized and active.
    // If the loader specified by the ID already exists, the last created loader is reused.
    // else  initLoader() triggers the LoaderManager.LoaderCallbacks method onCreateLoader().
    // This is where you implement the code to instantiate and return a new loader

    getLoaderManager().initLoader(0, null, this);        


    // We get ListView from Layout and initialize
    listView = (ListView) findViewById(R.id.textnote_list);

    // DB takes long, therefore this operation should take place in a new thread!                     
    new Handler().post(new Runnable() {
                @Override
                public void run() {
                    dataAdapter = new TextNoteAdapter(MainActivity.this, null, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
                    listView.setAdapter(dataAdapter);
                    Log.i("TAG", "MainActivity:: Handler... Run()");                       
                }
            });               

    listView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> listView, View view, int position, long id) {

                /** Get the cursor, positioned to the corresponding row in the result set **/
                Cursor cursor = (Cursor) listView.getItemAtPosition(position);               

                // display the selected note
                String noteName = cursor.getString(cursor.getColumnIndexOrThrow(TextNotesDb.KEY_NOTE_NAME));

                Toast.makeText(getApplicationContext(), noteName, Toast.LENGTH_SHORT).show();

                String rowId = cursor.getString(cursor.getColumnIndexOrThrow(TextNotesDb.KEY_ROWID));


                // starts a new Intent to update/delete a Textnote
                // pass in row Id to create the Content URI for a single row
                Intent intent = new Intent(getBaseContext(), TextNoteEdit.class);
                Bundle bundle = new Bundle();
                bundle.putString("mode", "update");
                bundle.putString("rowId", rowId);
                intent.putExtras(bundle);
                startActivityForResult(intent, 1);

            }
        });

    }    

    /** This is called when a new Loader needs to be created.**/
    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        Log.i("TAG", "MainActivity:: onCreateLoader");
        String[] projection = { 
                            TextNotesDb.KEY_ROWID,
                            TextNotesDb.KEY_GUID,
                            TextNotesDb.KEY_NOTE_NAME,
                            TextNotesDb.KEY_NOTE,
                            TextNotesDb.KEY_CREATION_DATE,
                            TextNotesDb.KEY_MODIFICATION_DATE
                           };
     CursorLoader cursorLoader = new CursorLoader(this, MyContentProvider.CONTENT_URI, projection, null, null, null);

        return cursorLoader;
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        // Swap the new cursor in.  (The framework will take care of closing the
        // old cursor once we return.)       
        dataAdapter.swapCursor(data);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        // This is called when the last Cursor provided to onLoadFinished()
        // above is about to be closed.  We need to make sure we are no
        // longer using it.
        dataAdapter.swapCursor(null);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }


}

回答1:


As in comment below my Question, I could solve it by adding 2 lines. Now it should look like this

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    // Swap the new cursor in.  (The framework will take care of closing the
    // old cursor once we return.)       
    dataAdapter.notifyDataSetChanged(); // <-
    listView.setAdapter(dataAdapter);   // <-
    dataAdapter.swapCursor(data);
}


来源:https://stackoverflow.com/questions/24447055/my-custom-cursoradapter-doesnt-update-my-listview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!