android - 使用 CursorAdapter 刷新 ListView 上的 SQLite 数据

标签 android listview android-sqlite android-adapter

Cant Refresh ListView and TextView

应用程序:我有一个应用程序可以创建多台机器:

  • _id、姓名和位置

每台机器我都要让用户输入 yield

  • _id, note, date, money, machines_id

问题OnLongClickListener 之后无法同时刷新 ListView 和 TextView

我尝试过的:Cursor Adapter,swapCursor。

我的问题:在同一个 Activity 中同时完成两件事的更新的最佳方法是什么?

如果您需要任何其他类(class)或有任何反馈,请随时关注我!

数据库助手

    public class DBHelpter extends SQLiteOpenHelper {

    private static final String DB_NAME = "machines.db";
    private static final int DB_VERSION = 1;

    public static final String TABLE_MACHINES = "machines";
    public static final String MACHINES_COLUMN_NAME = "name";
    public static final String MACHINES_COLUMN_LOCATION = "location";
    public static final String MACHINES_ID = "id";

    public static final String TABLE_INCOME = "income";
    public static final String INCOME_COLUMN_MONEY = "money";
    public static final String INCOME_COLUMN_DATE = "date";
    public static final String INCOME_COLUMN_NOTE = "note";
    public static final String INCOME_ID = "id";
    public static final String INCOME_COLUMN_MACHINES_ID = "machines_id";

    private Context mContext;

public DBHelpter(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

@Override
public void onCreate(SQLiteDatabase db) {
    String query1 = String.format("CREATE TABLE " + TABLE_MACHINES + "("
        + MACHINES_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
        + MACHINES_COLUMN_NAME + " TEXT NOT NULL, "
        + MACHINES_COLUMN_LOCATION + " TEXT NOT NULL)",
            TABLE_MACHINES, MACHINES_COLUMN_NAME, MACHINES_COLUMN_LOCATION, MACHINES_ID);

    String query2 = String.format("CREATE TABLE " + TABLE_INCOME + "("
        + INCOME_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
        + INCOME_COLUMN_MONEY + " REAL NOT NULL, "
        + INCOME_COLUMN_DATE + " DATE NOT NULL, "
        + INCOME_COLUMN_NOTE + " TEXT NOT NULL, "
        + INCOME_COLUMN_MACHINES_ID + " INTEGER NOT NULL)",
            TABLE_INCOME, INCOME_ID, INCOME_COLUMN_MONEY, INCOME_COLUMN_DATE, INCOME_COLUMN_NOTE, INCOME_COLUMN_MACHINES_ID);
    db.execSQL(query1);
    db.execSQL(query2);

}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    String query1 = String.format("DROP TABLE IF EXISTS " + TABLE_MACHINES);
    String query2 = String.format("DROP TABLE IF EXISTS " + TABLE_INCOME);
    db.execSQL(query1);
    db.execSQL(query2);
    onCreate(db);

}
public void insertNewMachine(String name, String location){
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(MACHINES_COLUMN_NAME, name);
        values.put(MACHINES_COLUMN_LOCATION, location);
        db.insertWithOnConflict(TABLE_MACHINES, null, values, SQLiteDatabase.CONFLICT_REPLACE);
        db.close();
    }
public void insertNewIncome(Double money, String date, String note, long machines_id){
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(INCOME_COLUMN_MONEY, money);
        values.put(INCOME_COLUMN_DATE, date);
        values.put(INCOME_COLUMN_NOTE, note);
        values.put(INCOME_COLUMN_MACHINES_ID, machines_id);
        db.insertWithOnConflict(TABLE_INCOME, null, values, SQLiteDatabase.CONFLICT_REPLACE);
        db.close();
    }
public void getIncomeOfMachine(long machinesId){
        SQLiteDatabase db = getReadableDatabase();
    Cursor cursor = db.rawQuery("SELECT machines_id, SUM(money) AS total FROM income WHERE machines_id = "+machinesId+"", null);
    cursor.moveToFirst();
    double total_amount = cursor.getDouble(cursor.getColumnIndex("total"));
    return total_amount;
    }
public ArrayList<MachinesClass> getAllMachines(){
        ArrayList<MachinesClass> machinesList = new ArrayList<>();
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery("SELECT * FROM "+ TABLE_MACHINES, null);
        while (cursor.moveToNext()){
            final long id = cursor.getLong(cursor.getColumnIndex(MACHINES_ID));
            final String name = cursor.getString(cursor.getColumnIndex(MACHINES_COLUMN_NAME));
            final String location = cursor.getString(cursor.getColumnIndex(MACHINES_COLUMN_LOCATION));
            machinesList.add(new MachinesClass(id, name, location));
        }
        cursor.close();
        db.close();
        return machinesList;
    }

public void deleteIncome(long id){
    SQLiteDatabase db = this.getWritableDatabase();
    db.delete(TABLE_INCOME, INCOME_ID+ "=?", new String[]{id + ""});
    db.close();
}

public Cursor getInfoOfMachine(long machinesId){
    SQLiteDatabase db = getReadableDatabase();
    Cursor cursor = db.rawQuery("SELECT _id, note, date, money FROM income WHERE machines_id = "+machinesId+" ORDER BY date ASC",null);
    return cursor;
}

游标适配器

public class ListAdapter extends CursorAdapter {


public ListAdapter(Context context, Cursor c) {
    super(context, c);
}

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

@Override
public void bindView(View view, final Context context, final Cursor cursor) {

    final DBHelpter mDBHelper = new DBHelpter(context);

    TextView mNote = (TextView) view.findViewById(R.id.tvNote);
    TextView mNotesDate = (TextView) view.findViewById(R.id.tvFecha);
    TextView mMoney = (TextView) view.findViewById(R.id.tvMoney);
    RelativeLayout mRelativeLayout = (RelativeLayout) view.findViewById(R.id.rlNotesList);

    final Long id = cursor.getLong(cursor.getColumnIndex("_id"));
    String note = cursor.getString(cursor.getColumnIndex("note"));
    String date = cursor.getString(cursor.getColumnIndex("date"));
    double money = cursor.getDouble(cursor.getColumnIndex("money"));

    mNote.setText(note);
    mNotesDate.setText(date);
    DecimalFormat formatter = new DecimalFormat("$#,##0.000");
    String formatted = formatter.format(money);
    mMoney.setText(formatted);

    mNote.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            AlertDialog alertDialog = new AlertDialog.Builder(v.getContext())
                    .setTitle("Confirmación")
                    .setMessage(Html.fromHtml("Segura de "+"<b>"+"BORRAR"+"</b>"+" la información?"))
                    .setNegativeButton("No", null)
                    .setPositiveButton("Si", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            mDBHelper.deleteIncome(id);
                            notifyDataSetChanged();
                        }
                    })
                    .create();
            alertDialog.show();
            return true;
        }
    });

}

机器信息

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

private TextView mLocation, mMoney;
private DBHelpter mDBHelpter;
private ListView mNotesList;
private FloatingActionButton mFAB;
private SQLiteDatabase db;
private Cursor mCursor;
private ListAdapter mAdapter;
private Context mContext;
private static final int LOADER_INTEGER = 1;

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

    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    mDBHelpter = new DBHelpter(getApplicationContext());
    db = mDBHelpter.getWritableDatabase();

    mLocation = (TextView) findViewById(R.id.tvLocation);
    mMoney = (TextView) findViewById(R.id.tvMoney);
    mFAB = (FloatingActionButton) findViewById(R.id.fabAddIncome);
    mNotesList = (ListView) findViewById(R.id.lvNotes);

    SharedPreferences mSharedPreferences = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
    final Long machines_id = mSharedPreferences.getLong("machines_id", 0);

    double total_amount = mDBHelpter.getIncomeOfMachine(machines_id);
    DecimalFormat formatter = new DecimalFormat("$#,##0.000");
    String formatted = formatter.format(total_amount);
    mMoney.setText(formatted);

    String location = mSharedPreferences.getString("location", null);
    mLocation.setText(location);

    mAdapter = new ListAdapter(this, mDBHelpter.getInfoOfMachine(machines_id));
    mAdapter.notifyDataSetChanged();
    mNotesList.setAdapter(mAdapter);

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

    mFAB.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent i = new Intent(getApplicationContext(), IncomeCreation.class);
            startActivity(i);
        }
    });
}


@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    SharedPreferences mSharedPreferences = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
    final Long machines_id = mSharedPreferences.getLong("machines_id", 0);
    String[] projection = new String[]{"_id", "note", "date", "money"};
    String selection = "machines_id = "+machines_id;
    String sortOrder = "date ASC";
    return new CursorLoader(this, IncomeProvider.CONTENT_URI, projection, selection, null, sortOrder);
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    mAdapter.swapCursor(cursor);
}

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

收入提供者

public class IncomeProvider extends ContentProvider {

private static final int INCOME = 1;
private static final int INCOME_ID = 2;
private static final String PROVIDER = "tech.destinum.machines.incomeprovider";
static final Uri CONTENT_URI = Uri.parse("content://"+ PROVIDER + "/income");
public static final UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static{
    mUriMatcher.addURI(PROVIDER, "income", INCOME);
    mUriMatcher.addURI(PROVIDER, "income/#", INCOME_ID);
}
private DBHelpter mDBHelper;
private SQLiteDatabase db;


@Override
public boolean onCreate() {
    Context context = getContext();
    mDBHelper = new DBHelpter(context);
    SQLiteDatabase db = mDBHelper.getWritableDatabase();
    return (db == null)? false:true;
}

@Nullable
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
    queryBuilder.setTables(DBHelpter.TABLE_INCOME);

    switch (mUriMatcher.match(uri)) {
        case INCOME:
            break;
        case INCOME_ID:
            queryBuilder.appendWhere(DBHelpter.INCOME_ID + "="
                    + uri.getLastPathSegment());
            break;
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
    }

    SharedPreferences mSharedPreferences = getContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
    final Long machines_id = mSharedPreferences.getLong("machines_id", 0);
    db = mDBHelper.getWritableDatabase();
    projection = new String[]{"_id", "note", "date", "money"};
    selection = "machines_id = "+machines_id;
    sortOrder = "date ASC";
    Cursor cursor = queryBuilder.query(db, projection, selection,
            selectionArgs, null, null, sortOrder);

    cursor.setNotificationUri(getContext().getContentResolver(), uri);
    return cursor;
}

@Nullable
@Override
public String getType(Uri uri) {
    return null;
}

@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {
    int uriType = mUriMatcher.match(uri);
    SQLiteDatabase sqlDB = mDBHelper.getWritableDatabase();
    long id = 0;
    switch (uriType) {
        case INCOME:
            id = sqlDB.insert(DBHelpter.TABLE_INCOME, null, values);
            break;
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
    }
    getContext().getContentResolver().notifyChange(uri, null);
    return Uri.parse("income" + "/" + id);
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    int uriType = mUriMatcher.match(uri);
    SQLiteDatabase sqlDB = mDBHelper.getWritableDatabase();
    int rowsDeleted = 0;
    switch (uriType) {
        case INCOME:
            rowsDeleted = sqlDB.delete(DBHelpter.TABLE_INCOME, selection,
                    selectionArgs);
            break;
        case INCOME_ID:
            String id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsDeleted = sqlDB.delete(
                        DBHelpter.TABLE_INCOME,
                        DBHelpter.INCOME_ID + "=" + id,
                        null);
            } else {
                rowsDeleted = sqlDB.delete(
                        DBHelpter.TABLE_INCOME,
                        DBHelpter.INCOME_ID + "=" + id
                                + " and " + selection,
                        selectionArgs);
            }
            break;
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
    }
    getContext().getContentResolver().notifyChange(uri, null);
    return rowsDeleted;
}

@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    int uriType = mUriMatcher.match(uri);
    SQLiteDatabase sqlDB = mDBHelper.getWritableDatabase();
    int rowsUpdated = 0;
    switch (uriType) {
        case INCOME:
            rowsUpdated = sqlDB.update(DBHelpter.TABLE_INCOME,
                    values,
                    selection,
                    selectionArgs);
            break;
        case INCOME_ID:
            String id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsUpdated = sqlDB.update(DBHelpter.TABLE_INCOME,
                        values,
                        DBHelpter.INCOME_ID + "=" + id,
                        null);
            } else {
                rowsUpdated = sqlDB.update(DBHelpter.TABLE_INCOME,
                        values,
                        DBHelpter.INCOME_ID + "=" + id
                                + " and "
                                + selection,
                        selectionArgs);
            }
            break;
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
    }
    getContext().getContentResolver().notifyChange(uri, null);
    return rowsUpdated;
}

最佳答案

也许你可以尝试使用Loaders .

它们让您将数据源(Content Provider 或其他)与 Activity 或 Fragment 绑定(bind)。当加载器处于 Activity 状态时,它们应该监视数据源并在内容更改时提供新结果。

我会给你一个通用的方法来实现它们(特别是 CursorLoader):

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

    private static final int LOADER_INTEGER = 1;

    // ... existing code

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        getLoaderManager().initLoader(LOADER_INTEGER, null, this);
        super.onActivityCreated(savedInstanceState);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        return new CursorLoader(
            this,
            ContentProvider.CONTENT_URI,
            projection,
            null,
            null,
            sortOrder
        );
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        mCursorAdapter.swapCursor(cursor);
    }

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

你可以在互联网上阅读很多关于这方面的内容,一个好的开始是例如 here .

希望对你有帮助

关于android - 使用 CursorAdapter 刷新 ListView 上的 SQLite 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42034011/

相关文章:

java - Android sqlite更新方法; java.lang.IllegalStateException : Could not execute method of the activity

java - Android 插入数据库时​​出错,代码 19 : constraint failed

Android - 触摸绘图

android - Firebase 存储最佳实践

java - 设置 SQLite 列默认值时如何使用字符串常量

listview - 如何在标签中重用Listview?

Android在Adapter的GetView方法中获取ListView的宽度

java - ListView HashMap Firebase

java - Android 如何将字符串数组设置为单个 TextView

sqlite - 为什么具有整数数据类型的列也在 SQL 数据库中存储浮点值