简单光标适配器,具有内部联接的内容提供程序仅显示一次数据

时间:2016-07-09 11:13:59

标签: android listview android-cursor android-syncadapter

我有问题,我的ListView只显示一次数据。如果我关闭应用程序并再次打开它,它就不会显示任何内容。

我有一个Content Provider,用于从SQLite数据库中检索数据。我有一个SyncAdapter,它从服务器获取数据并将其放入SQLite数据库。然后我使用SimpleCursorAdapter将数据显示到ListView中。该查询是一个内部联接'。

MainActivity Code:

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

    private static final int URL_LOADER = 1;
    private ListView employeeList;
    public static SimpleCursorAdapter adapter;

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

        employeeList = (ListView) findViewById(R.id.listView);

        /**
         * Creating a dummyAccount for the content provider
         */
        Account account = new Account("dummyAccount", TrackingContentProvider.AUTHORITY);
        AccountManager accountManager = (AccountManager) this.getSystemService(ACCOUNT_SERVICE);
        accountManager.addAccountExplicitly(account, null, null);

        /**
         * Set the sync adapter to an automatic state
         */
        ContentResolver.setSyncAutomatically(account, TrackingContentProvider.AUTHORITY, true);

        /**
         * The projection for the SimpleCursorLoader
         */
        String[] from = new String[] {EmployeesTable.COLUMN_FIRST_NAME, EmployeesTable.COLUMN_LAST_NAME, StatesTable.COLUMN_STATE, EmployeesTable.COLUMN_ID};

        /**
         * The ids of the views where the content is going to be put in
         */
        int[] to = new int[] {R.id.tV_emplFirstNameInsert, R.id.tV_emplLastNameInsert, R.id.tV_stateInsert};

        /**
         * Make a new cursor adapter for the list view
         */
        adapter = new SimpleCursorAdapter(this, R.layout.employee_list_item, null, from, to, 0);

        /**
         * Calls the loader manager and query another time
         */
        getSupportLoaderManager().restartLoader(URL_LOADER, null, MainActivity.this);

        /**
         * Sets the list view to the SimpleCursorAdapter
         */
        employeeList.setAdapter(adapter);

        registerClickCallback();
    }

    /**
     * Registers the clicks on the elements
     */
    private void registerClickCallback() {
        employeeList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                startActivity(new Intent(MainActivity.this, LocationActivity.class));
            }
        });
    }

    /**
     * Is called by the loader manager
     * @param id The unique id of the loader
     * @param args Bundle of arguments
     * @return The cursor of the query
     */
    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        String[] projection = new String[] {"E." + EmployeesTable.COLUMN_ID, "E." + EmployeesTable.COLUMN_FIRST_NAME,
                "E." + EmployeesTable.COLUMN_LAST_NAME, "S." + StatesTable.COLUMN_STATE};
        String clause = "S." + StatesTable.COLUMN_ID + " = " + "E." + EmployeesTable.COLUMN_STATE_ID;
        return new CursorLoader(this,
                TrackingContentProvider.EMPLOYEE_LIST_CONTENT_URI, projection, clause, null, null);
    }

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

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

    @Override
    protected void onRestart() {
        super.onRestart();
        getSupportLoaderManager().restartLoader(URL_LOADER, null, MainActivity.this);
    }
}

Content Provider使用SQLiteQueryBuilder查询数据。我用于查询的表格如下所示:

private static final String EMPLOYEE_LIST_INNER_JOIN = "" +
        EmployeesTable.TABLE_NAME + " AS E " +
        "INNER JOIN " +
        StatesTable.TABLE_NAME + " AS S";

onPerformSync如下所示:

@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
    try {
        deleteDatabase(provider);
        insertEmployeesTable(provider);
        insertStatesTable(provider);
        insertLocationsTable(provider);
    } catch (RemoteException | IOException e) {
        Log.e("Sync: Error:", e.toString());
    }
}

因此,每次同步时,它都会删除数据库的所有条目并插入新数据。它有效,我在同步后检查了数据库。

首次启动应用程序后,由于同步适配器正在同步,因此它不会显示任何内容。然后我关闭应用程序并再次打开它,它显示数据。然后同步适配器同步另一个时间(相同的数据),但它不再显示数据。有什么建议?我现在正试图找错误3天......

编辑1:ContentProvider代码:

public class TrackingContentProvider extends ContentProvider {
private static final int TRACKING_CONTENT = 100;
private static final int TRACKING_CONTENT_ID = 200;
private static final int EMPLOYEE_LIST_CONTENT = 300;
private static final int EMPLOYEE_LIST_CONTENT_ID = 400;

/**
 * Table declaration
 */
private static final int EMPLOYEES_TABLE_CONTENT = 500;
private static final int EMPLOYEES_TABLE_CONTENT_ID = 600;
private static final int STATES_TABLE_CONTENT = 700;
private static final int STATES_TABLE_CONTENT_ID = 800;
private static final int LOCATIONS_TABLE_CONTENT = 900;
private static final int LOCATIONS_TABLE_CONTENT_ID = 1000;

public static final String AUTHORITY = "***";
private static final String TRACKING_BASE_PATH = "tracking";
private static final String EMPLOYEE_LIST_BASE_PATH = "employees";

/**
 * Table base paths
 */
private static final String EMPLOYEES_TABLE_BASE_PATH = "employeesTable";
private static final String STATES_TABLE_BASE_PATH = "statesTable";
private static final String LOCATIONS_TABLE_BASE_PATH = "locationsTable";

/**
 * Table INNER JOIN declarations
 */
private static final String EMPLOYEE_LIST_INNER_JOIN = "" +
        EmployeesTable.TABLE_NAME + " AS E " +
        "INNER JOIN " +
        StatesTable.TABLE_NAME + " AS S";

public static final Uri TRACKING_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + TRACKING_BASE_PATH);
public static final Uri EMPLOYEE_LIST_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + EMPLOYEE_LIST_BASE_PATH);

/**
 * Tables Uris
 */
public static final Uri EMPLOYEES_TABLE_URI = Uri.parse("content://" + AUTHORITY + "/" + EMPLOYEES_TABLE_BASE_PATH);
public static final Uri STATES_TABLE_URI = Uri.parse("content://" + AUTHORITY + "/" + STATES_TABLE_BASE_PATH);
public static final Uri LOCATIONS_TABLE_URI = Uri.parse("content://" + AUTHORITY + "/" + LOCATIONS_TABLE_BASE_PATH);

private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

static {
    sUriMatcher.addURI(AUTHORITY, TRACKING_BASE_PATH, TRACKING_CONTENT);
    sUriMatcher.addURI(AUTHORITY, TRACKING_BASE_PATH + "/#", TRACKING_CONTENT_ID);
    sUriMatcher.addURI(AUTHORITY, EMPLOYEE_LIST_BASE_PATH, EMPLOYEE_LIST_CONTENT);
    sUriMatcher.addURI(AUTHORITY, EMPLOYEE_LIST_BASE_PATH + "/#", EMPLOYEE_LIST_CONTENT_ID);

    /**
     * Table matcher
     */
    sUriMatcher.addURI(AUTHORITY, EMPLOYEES_TABLE_BASE_PATH, EMPLOYEES_TABLE_CONTENT);
    sUriMatcher.addURI(AUTHORITY, EMPLOYEES_TABLE_BASE_PATH + "/#", EMPLOYEES_TABLE_CONTENT_ID);
    sUriMatcher.addURI(AUTHORITY, STATES_TABLE_BASE_PATH, STATES_TABLE_CONTENT);
    sUriMatcher.addURI(AUTHORITY, STATES_TABLE_BASE_PATH + "/#", STATES_TABLE_CONTENT_ID);
    sUriMatcher.addURI(AUTHORITY, LOCATIONS_TABLE_BASE_PATH, LOCATIONS_TABLE_CONTENT);
    sUriMatcher.addURI(AUTHORITY, LOCATIONS_TABLE_BASE_PATH + "/#", LOCATIONS_TABLE_CONTENT_ID);
}

private SQLiteHelper database;

@Override
public boolean onCreate() {
    database = new SQLiteHelper(getContext());
    return false;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
    int uriType = sUriMatcher.match(uri);
    checkColumns(projection);

    switch (uriType) {
        case TRACKING_CONTENT:
            break;
        case TRACKING_CONTENT_ID:
            break;
        case EMPLOYEE_LIST_CONTENT:
            queryBuilder.setTables(EMPLOYEE_LIST_INNER_JOIN);
            break;
        case EMPLOYEE_LIST_CONTENT_ID:
            queryBuilder.setTables(EMPLOYEE_LIST_INNER_JOIN);
            queryBuilder.appendWhere("E." + EmployeesTable.COLUMN_ID + " = " + uri.getLastPathSegment());
            break;
        case STATES_TABLE_CONTENT:
            queryBuilder.setTables(StatesTable.TABLE_NAME);
            break;
        case STATES_TABLE_CONTENT_ID:
            queryBuilder.setTables(StatesTable.TABLE_NAME);
            queryBuilder.appendWhere(StatesTable.COLUMN_ID + " = " + uri.getLastPathSegment());
            break;
        case EMPLOYEES_TABLE_CONTENT:
            queryBuilder.setTables(EmployeesTable.TABLE_NAME);
            break;
        case EMPLOYEES_TABLE_CONTENT_ID:
            queryBuilder.setTables(EmployeesTable.TABLE_NAME);
            queryBuilder.appendWhere(EmployeesTable.COLUMN_ID + " = " + uri.getLastPathSegment());
            break;
        case LOCATIONS_TABLE_CONTENT:
            queryBuilder.setTables(LocationsTable.TABLE_NAME);
            break;
        case LOCATIONS_TABLE_CONTENT_ID:
            queryBuilder.setTables(LocationsTable.TABLE_NAME);
            queryBuilder.appendWhere(LocationsTable.COLUMN_ID + " = " + uri.getLastPathSegment());
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
    }

    SQLiteDatabase db = database.getReadableDatabase();
    Cursor cursor = queryBuilder.query(
            db,
            projection,
            selection,
            selectionArgs,
            null,
            null,
            sortOrder
    );
    cursor.setNotificationUri(getContext().getContentResolver(), uri);

    return cursor;
}

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

@Override
public Uri insert(Uri uri, ContentValues values) {
    int uriType = sUriMatcher.match(uri);
    SQLiteDatabase db = database.getWritableDatabase();
    long id;
    String path;

    switch (uriType) {
        case STATES_TABLE_CONTENT:
            id = db.insert(StatesTable.TABLE_NAME, null, values);
            path = STATES_TABLE_BASE_PATH;
            break;
        case LOCATIONS_TABLE_CONTENT:
            id = db.insert(LocationsTable.TABLE_NAME, null, values);
            path = LOCATIONS_TABLE_BASE_PATH;
            break;
        case EMPLOYEES_TABLE_CONTENT:
            id = db.insert(EmployeesTable.TABLE_NAME, null, values);
            path = EMPLOYEES_TABLE_BASE_PATH;
            break;
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
    }
    getContext().getContentResolver().notifyChange(uri, null);
    return Uri.parse(path + "/" + id);
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    int uriType = sUriMatcher.match(uri);
    SQLiteDatabase db = database.getWritableDatabase();
    int rowsDeleted = 0;

    switch (uriType) {
        case EMPLOYEES_TABLE_CONTENT:
            rowsDeleted = db.delete(EmployeesTable.TABLE_NAME,
                    selection,
                    selectionArgs);
            break;
        case EMPLOYEES_TABLE_CONTENT_ID:
            String employeeID = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsDeleted = db.delete(EmployeesTable.TABLE_NAME,
                        EmployeesTable.COLUMN_ID + " = " + employeeID, null);
            }
            break;
        case STATES_TABLE_CONTENT:
            rowsDeleted = db.delete(StatesTable.TABLE_NAME,
                    selection,
                    selectionArgs);
            break;
        case STATES_TABLE_CONTENT_ID:
            String stateID = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsDeleted = db.delete(StatesTable.TABLE_NAME,
                        StatesTable.COLUMN_ID + " = " + stateID, null);
            }
            break;
        case LOCATIONS_TABLE_CONTENT:
            rowsDeleted = db.delete(StatesTable.TABLE_NAME,
                    selection,
                    selectionArgs);
            break;
        case LOCATIONS_TABLE_CONTENT_ID:
            String locationID = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsDeleted = db.delete(LocationsTable.TABLE_NAME,
                        LocationsTable.COLUMN_ID + " = " + locationID, null);
            }
            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 = sUriMatcher.match(uri);
    SQLiteDatabase sqlDb = database.getWritableDatabase();
    int rowsUpdated;
    switch (uriType) {
        case EMPLOYEES_TABLE_CONTENT:
            rowsUpdated = sqlDb.update(EmployeesTable.TABLE_NAME,
                    values,
                    selection,
                    selectionArgs);
            break;
        case EMPLOYEE_LIST_CONTENT_ID:
            String employeeID = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsUpdated = sqlDb.update(EmployeesTable.TABLE_NAME,
                        values,
                        EmployeesTable.COLUMN_ID + "=" + employeeID
                                + " AND "
                                + selection,
                        selectionArgs);
            } else {
                rowsUpdated = sqlDb.update(EmployeesTable.TABLE_NAME,
                        values,
                        EmployeesTable.COLUMN_ID + "=" + employeeID
                                + " AND "
                                + selection,
                        selectionArgs);
            }
            break;
        case STATES_TABLE_CONTENT:
            rowsUpdated = sqlDb.update(StatesTable.TABLE_NAME,
                    values,
                    selection,
                    selectionArgs);
            break;
        case STATES_TABLE_CONTENT_ID:
            String stateID = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsUpdated = sqlDb.update(StatesTable.TABLE_NAME,
                        values,
                        StatesTable.COLUMN_ID + "=" + stateID
                                + " AND "
                                + selection,
                        selectionArgs);
            } else {
                rowsUpdated = sqlDb.update(StatesTable.TABLE_NAME,
                        values,
                        StatesTable.COLUMN_ID + "=" + stateID
                                + " AND "
                                + selection,
                        selectionArgs);
            }
            break;
        case LOCATIONS_TABLE_CONTENT:
            rowsUpdated = sqlDb.update(LocationsTable.TABLE_NAME,
                    values,
                    selection,
                    selectionArgs);
            break;
        case LOCATIONS_TABLE_CONTENT_ID:
            String locationID = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsUpdated = sqlDb.update(LocationsTable.TABLE_NAME,
                        values,
                        LocationsTable.COLUMN_ID + "=" + locationID
                                + " AND "
                                + selection,
                        selectionArgs);
            } else {
                rowsUpdated = sqlDb.update(LocationsTable.TABLE_NAME,
                        values,
                        LocationsTable.COLUMN_ID + "=" + locationID
                                + " AND "
                                + selection,
                        selectionArgs);
            }
            break;
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
    }

    getContext().getContentResolver().notifyChange(uri, null);
    return rowsUpdated;
}

/**
 * Checks if the column exists
 * @param projection The array of the existing columns
 */
private void checkColumns(String[] projection) {
    String[] available = {
            "E." + EmployeesTable.COLUMN_ID,
            "E." + EmployeesTable.COLUMN_LAST_NAME,
            "E." + EmployeesTable.COLUMN_FIRST_NAME,
            "E." + EmployeesTable.COLUMN_STATE_ID,
            "E." + EmployeesTable.COLUMN_ENTRY_DATE,

            "S." + StatesTable.COLUMN_ID,
            "S." + StatesTable.COLUMN_STATE,

            "L." + LocationsTable.COLUMN_ID,
            "L." + LocationsTable.COLUMN_DATE,
            "L." + LocationsTable.COLUMN_EMPLOYEE_ID,
            "L." + LocationsTable.COLUMN_LONGITUDE,
            "L." + LocationsTable.COLUMN_LATITUDE,

            EmployeesTable.COLUMN_ID,
            EmployeesTable.COLUMN_LAST_NAME,
            EmployeesTable.COLUMN_FIRST_NAME,
            EmployeesTable.COLUMN_STATE_ID,
            EmployeesTable.COLUMN_ENTRY_DATE,

            StatesTable.COLUMN_ID,
            StatesTable.COLUMN_STATE,

            LocationsTable.COLUMN_ID,
            LocationsTable.COLUMN_DATE,
            LocationsTable.COLUMN_EMPLOYEE_ID,
            LocationsTable.COLUMN_LONGITUDE,
            LocationsTable.COLUMN_LATITUDE,

    };

    if (projection != null) {
        HashSet<String> requestedColumns = new HashSet<>(Arrays.asList(projection));
        HashSet<String> availableColumns = new HashSet<>(Arrays.asList(available));

        if (!availableColumns.containsAll(requestedColumns)) {
            throw new IllegalArgumentException("Unknown columns in projection");
        }
    }
}

}

更新:
我终于找到了错误。在同步期间,自动增量出错。所以,他没有找到这个Inner Join声明的条目。结束。

0 个答案:

没有答案