ListView显示两次数据

时间:2018-04-09 19:51:05

标签: android database listview android-cursoradapter android-cursorloader

我正在开发一个小应用程序,用于在数据库中保存书籍的数据(例如书籍的名称,书籍的类型,书籍的作者和出版年份),但是当数据使用 CursorLoader 从数据库返回它在 ListView

中显示两次
  

这是 AddBook 活动的代码。

package training.android.com.librarycard;

import android.app.AlertDialog;
import android.app.LoaderManager;
import android.content.ContentValues;
import android.content.CursorLoader;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;

import training.android.com.librarycard.Database.Database;
import training.android.com.librarycard.Database.LibraryCardContract;

public class AddBook extends AppCompatActivity
        implements LoaderManager.LoaderCallbacks<Cursor> {

    private static final int EXISTING_BOOK_LOADER = 0;
    Spinner mBookType;
    EditText mBookTitle, mBookAuthor, mBookPublishYear;
    String bookType;
    int position;
    private boolean bookHasChanged = false;

    private Uri currentBookUri;

    private View.OnTouchListener touchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            bookHasChanged = true;
            return false;
        }
    };


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

        Intent intent = getIntent();
        if (intent != null) {
            currentBookUri = intent.getData();

            if (currentBookUri == null) {
                setTitle("Add a book");
                invalidateOptionsMenu();
            } else {
                setTitle("Edit a book");
                getLoaderManager().initLoader(EXISTING_BOOK_LOADER, null, this);
            }

        }

        mBookType = findViewById(R.id.spinner);
        mBookTitle = findViewById(R.id.book_title);
        mBookAuthor = findViewById(R.id.book_author);
        mBookPublishYear = findViewById(R.id.publish_year);

        mBookType.setOnTouchListener(touchListener);
        mBookAuthor.setOnTouchListener(touchListener);
        mBookTitle.setOnTouchListener(touchListener);
        mBookPublishYear.setOnTouchListener(touchListener);


        setupBookTypeSpinner();


    }

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

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);
        if (currentBookUri == null) {
            MenuItem menuItem = menu.findItem(R.id.action_delete);
            menuItem.setVisible(false);
        }

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        switch (id) {
            case R.id.action_save:
                setBook();
                finish();
                return true;
            case R.id.action_delete:
                showDeleteConfirmationDialog();
                return true;
            case android.R.id.home:
                if (!bookHasChanged) {
                    NavUtils.navigateUpFromSameTask(AddBook.this);
                    return true;
                }
                DialogInterface.OnClickListener discardButtonClickListener
                        = new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        NavUtils.navigateUpFromSameTask(AddBook.this);
                    }
                };

                showUnsavedChangeDialog(discardButtonClickListener);
                return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private void showUnsavedChangeDialog(DialogInterface.OnClickListener discardButtonClickListener) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("Discard your changes and quit editing?");
        builder.setPositiveButton("Discard", discardButtonClickListener);
        builder.setNegativeButton("Keep editing", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (dialog != null)
                    dialog.dismiss();
            }
        });

        AlertDialog alertDialog = builder.create();
        alertDialog.show();

    }

    private void showDeleteConfirmationDialog() {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("Delete this book ?");
        builder.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                deleteBook();
            }
        });

        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (dialog != null)
                    dialog.dismiss();
            }
        });

        AlertDialog alertDialog = builder.create();
        alertDialog.show();
    }

    private void deleteBook() {
        if (currentBookUri != null) {
            int rowDeleted = getContentResolver().delete(currentBookUri, null, null);
            if (rowDeleted == 0)
                Toast.makeText(this, "Delete book failed", Toast.LENGTH_SHORT).show();
            else
                Toast.makeText(this, "Delete book successful", Toast.LENGTH_SHORT).show();

        }

        finish();

    }


    public void setupBookTypeSpinner() {
        final ArrayAdapter<CharSequence> bookTypeAdapter = ArrayAdapter.createFromResource(
                this, R.array.books_type, R.layout.support_simple_spinner_dropdown_item);
        bookTypeAdapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
        mBookType.setAdapter(bookTypeAdapter);

        mBookType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                bookType = parent.getSelectedItem().toString();
                position = parent.getSelectedItemPosition();
                Log.i("BookTypeSelection", bookType+"");

            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

    }

    public void setBook() {
        String bookTitle = mBookTitle.getText().toString().trim();
        String bookAuthor = mBookAuthor.getText().toString().trim();
        String publishYear = mBookPublishYear.getText().toString().trim();

        if (currentBookUri == null && TextUtils.isEmpty(bookTitle) && TextUtils.isEmpty(bookAuthor)
                 && TextUtils.isEmpty(publishYear))
            return;

        Database database = new Database(this);
        SQLiteDatabase db = database.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(LibraryCardContract.LibraryCard.COLUMN_BOOK_TITLE, bookTitle);
        values.put(LibraryCardContract.LibraryCard.COLUMN_BOOK_AUTHOR, bookAuthor);
        values.put(LibraryCardContract.LibraryCard.COLUMN_BOOK_PUBLISH_YEAR, publishYear);
        values.put(LibraryCardContract.LibraryCard.COLUMN_BOOK_TYPE, bookType);

        if (currentBookUri == null) {
            Uri uri = getContentResolver().insert(LibraryCardContract.LibraryCard.CONTENT_URI, values);
            if (uri == null) {
                Toast.makeText(this, "Error with saving book", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, "Book saved", Toast.LENGTH_SHORT).show();
            }
        } else {
            int rowAffected = getContentResolver().update(currentBookUri, values, null, null);
            if (rowAffected == 0) {
                Toast.makeText(this, "Error with saving book", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, "Book saved", Toast.LENGTH_SHORT).show();
            }
        }

        db.insert(LibraryCardContract.LibraryCard.TABLE_NAME, null, values);
        Toast.makeText(this, "Insert new book", Toast.LENGTH_SHORT).show();

    }


    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        String [] projection = {
                LibraryCardContract.LibraryCard.COLUMN_BOOK_TITLE,
                LibraryCardContract.LibraryCard.COLUMN_BOOK_TYPE,
                LibraryCardContract.LibraryCard.COLUMN_BOOK_AUTHOR,
                LibraryCardContract.LibraryCard.COLUMN_BOOK_PUBLISH_YEAR };
        return new CursorLoader(this,currentBookUri,projection,
                null,null,null);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        if(data.moveToFirst()){
            String title = data.getString(
                    data.getColumnIndexOrThrow(LibraryCardContract.LibraryCard.COLUMN_BOOK_TITLE));
            String type = data.getString(
                    data.getColumnIndexOrThrow(LibraryCardContract.LibraryCard.COLUMN_BOOK_TYPE));
            String publishYear = data.getString(
                    data.getColumnIndexOrThrow(LibraryCardContract.LibraryCard.COLUMN_BOOK_PUBLISH_YEAR));
            String author = data.getString(
                    data.getColumnIndexOrThrow(LibraryCardContract.LibraryCard.COLUMN_BOOK_AUTHOR));

            mBookTitle.setText(title);
            mBookAuthor.setText(author);
            mBookType.setSelection(position);
            mBookPublishYear.setText(publishYear);

        }

    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        mBookTitle.setText("");
        mBookType.setSelection(position);
        mBookAuthor.setText("");
        mBookPublishYear.setText("");

    }

    @Override
    public void onBackPressed() {
        if(!bookHasChanged){
            super.onBackPressed();
            return;
        }

        DialogInterface.OnClickListener discardButtonClickListener =
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        finish();
                    }
                };

        showUnsavedChangeDialog(discardButtonClickListener);
    }





}
  

这是主页活动的代码,其中包含 listView   显示数据。

   package training.android.com.librarycard;

    import android.app.LoaderManager;
    import android.content.ContentUris;
    import android.content.CursorLoader;
    import android.content.Intent;
    import android.content.Loader;
    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Bundle;
    import android.support.design.widget.FloatingActionButton;
    import android.support.design.widget.NavigationView;
    import android.support.v4.view.GravityCompat;
    import android.support.v4.widget.DrawerLayout;
    import android.support.v7.app.ActionBarDrawerToggle;
    import android.support.v7.app.AppCompatActivity;
    import android.support.v7.widget.Toolbar;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.ListView;

    import java.util.ArrayList;
    import java.util.List;

    import training.android.com.librarycard.Database.Database;
    import training.android.com.librarycard.Database.LibraryCardContract;
    import training.android.com.librarycard.Models.BookCursorAdapter;
    import training.android.com.librarycard.Models.BookDetail;

    public class Home extends AppCompatActivity
            implements NavigationView.OnNavigationItemSelectedListener, LoaderManager.LoaderCallbacks<Cursor> {

        private static final int BOOK_LOADER = 0;
        private ListView mBookList;
        private BookCursorAdapter cursorAdapter;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_home);
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);

            mBookList = findViewById(R.id.books_rv);

            cursorAdapter = new BookCursorAdapter(this, null);
            mBookList.setAdapter(cursorAdapter);

            mBookList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    Intent intent = new Intent(Home.this, AddBook.class);
                    Uri currentPetUri = ContentUris.withAppendedId(LibraryCardContract.LibraryCard.CONTENT_URI, id);
                    intent.setData(currentPetUri);
                    startActivity(intent);
                }
            });

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


            FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
            fab.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent intent = new Intent(getBaseContext(), AddBook.class);
                    startActivity(intent);
                }
            });

            DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
            ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                    this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
            drawer.addDrawerListener(toggle);
            toggle.syncState();

            NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
            navigationView.setNavigationItemSelectedListener(this);
        }

        @Override
        public void onBackPressed() {
            DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
            if (drawer.isDrawerOpen(GravityCompat.START)) {
                drawer.closeDrawer(GravityCompat.START);
            } else {
                super.onBackPressed();
            }
        }

        @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, menu);
            return true;
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();

            switch (id) {
                case R.id.delete_all_books:
                    deleteAllBooks();
                    return true;
            }

            //noinspection SimplifiableIfStatement


            return super.onOptionsItemSelected(item);
        }

        private void deleteAllBooks() {
            int rowDeleted = getContentResolver().delete(LibraryCardContract.LibraryCard.CONTENT_URI,
                    null, null);
        }

        @SuppressWarnings("StatementWithEmptyBody")
        @Override
        public boolean onNavigationItemSelected(MenuItem item) {
            // Handle navigation view item clicks here.
            int id = item.getItemId();


            DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
            drawer.closeDrawer(GravityCompat.START);
            return true;
        }

        @Override
        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
            String[] projection = {
                    LibraryCardContract.LibraryCard._ID,
                    LibraryCardContract.LibraryCard.COLUMN_BOOK_TITLE,
                    LibraryCardContract.LibraryCard.COLUMN_BOOK_AUTHOR,
                    LibraryCardContract.LibraryCard.COLUMN_BOOK_TYPE,
                    LibraryCardContract.LibraryCard.COLUMN_BOOK_PUBLISH_YEAR};

            return new CursorLoader(this, LibraryCardContract.LibraryCard.CONTENT_URI,
                    projection,
                    null,
                    null,
                    null);

        }

        @Override
        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
            cursorAdapter.swapCursor(data);

        }

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

        }


    }

> This is a code of **BookCursorAdapter** class.
package training.android.com.librarycard.Models;

import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.TextView;

import training.android.com.librarycard.Database.LibraryCardContract;
import training.android.com.librarycard.R;

/**
 * Created by Hassan on 4/9/2018.
 */

public class BookCursorAdapter extends CursorAdapter {
    public BookCursorAdapter(Context context, Cursor c) {
        super(context, c, 0);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return LayoutInflater.from(context)
                .inflate(R.layout.book_list,parent,false);
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        TextView bookTitle = view.findViewById(R.id.book_name_tv);
        TextView bookAuthor = view.findViewById(R.id.author_tv);
        TextView bookType = view.findViewById(R.id.book_type_tv);
        TextView publishYear = view.findViewById(R.id.publish_year_tv);

        String title = cursor.getString(
                cursor.getColumnIndexOrThrow(LibraryCardContract.LibraryCard.COLUMN_BOOK_TITLE));
        String type = cursor.getString(
                cursor.getColumnIndexOrThrow(LibraryCardContract.LibraryCard.COLUMN_BOOK_TYPE));
        String year = cursor.getString(
                cursor.getColumnIndexOrThrow(LibraryCardContract.LibraryCard.COLUMN_BOOK_PUBLISH_YEAR));
        String author = cursor.getString(
                cursor.getColumnIndexOrThrow(LibraryCardContract.LibraryCard.COLUMN_BOOK_AUTHOR));


        bookAuthor.setText(author);
        bookTitle.setText(title);
        bookType.setText(type);
        publishYear.setText(year);



    }

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

应用程序的屏幕截图   enter image description here

0 个答案:

没有答案