1
我有計數器應用程序,我已經使用SimpleCursorAdapter
,ListView
和StartManagingCursor()
。現在我想用新的CursorLoader
和Contentprovider
。我寫了我自己的ContentProvider
並在MainActivity
上實現。正如你上面看到我的應用程序,當我點擊加號按鈕並更新計數時,它是滯後的。我每秒做大約2次點擊,但無法快速處理。我使用ContentResolver
進行更新。CursorLoader,ContentProvider太慢了
老辦法,startManagingCursor
,速度很快。
代碼在這裏,如果我在ContentProvider
或CursorLoader
上有任何錯誤,請幫助我。
MAIN.java
public class Main extends ActionBarActivity implements LoaderCallbacks<Cursor> {
Cursor cursor;
String[] FROM = { Database.C_NAME, Database.C_VALUE };// get values from db
int[] TO = { R.id.textMainName, R.id.textMainValue };// set values of item
SimpleCursorAdapter adapter;
boolean clickP;
boolean clickN;
boolean clickR;
String Lng;
private static final int URL_LOADER = 0;
private ListView mListView;
private ChannelAdapter mAdapter ;
ContentResolver cr ;
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mListView = (ListView) findViewById(R.id.list);
mAdapter =new ChannelAdapter(this, R.layout.list_item,null, FROM, TO,0);
mListView.setAdapter(mAdapter);
getSupportLoaderManager().initLoader(URL_LOADER, null, this);
registerForContextMenu(mListView);
}
@Override
protected void onResume() {
getSupportLoaderManager().restartLoader(0, null, this); }
public class ChannelAdapter extends SimpleCursorAdapter {
@SuppressWarnings("deprecation")
public ChannelAdapter(Context context, int layout, Cursor c,
String[] from, int[] to,int flag) {
super(context, layout, c, from, to, flag);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_item, parent, false);
Button bP = (Button) convertView.findViewById(R.id.buttonMainPlus);
final TextView tvName = (TextView) convertView.findViewById(R.id.textMainName);
final TextView tvValue = (TextView) convertView.findViewById(R.id.textMainValue);
// When plus button is clicked
bP.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
int valuer = Integer.parseInt(tvValue.getText().toString());
ContentValues updatedValues = new ContentValues();
updatedValues.put(Database.C_VALUE,valuer+1);
//Uri rowURI =ContentUris.withAppendedId(MyContentProvider.CONTENT_URI,hoardId);
// Specify a specific row so no selection clause is required.
String where = Database.C_NAME+ " = '" + tvName.getText().toString() + "'" ;
String whereArgs[] = null;
// Get the Content Resolver.
cr = getContentResolver();
// Update the specified row.
int updatedRowCount = cr.update(MyContentProvider.CONTENT_URI, updatedValues, where, whereArgs);
}
});
return super.getView(position, convertView, parent);
}
}
@Override
public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle) {
switch (loaderID) {
case URL_LOADER:
return new CursorLoader(Main.this,MyContentProvider.CONTENT_URI,null,null,null,null);
default:
return null;
}
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
mAdapter.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> arg0) {
mAdapter.swapCursor(null);
}
}
MyContentProvider.java
public class MyContentProvider extends ContentProvider{
// database
private Database database;
private static final int ALL_ROWS = 1;
private static final int SINGLE_ROW= 2;
public static final String KEY_ID = "_id";
private static final String AUTHORITY = "com.example.counter.contentprovider";
private static final String BASE_PATH = "list";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);//uri
public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE+ "/todos";
public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/todo";
private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
sURIMatcher.addURI(AUTHORITY, BASE_PATH, ALL_ROWS);
sURIMatcher.addURI(AUTHORITY, BASE_PATH + "/#", SINGLE_ROW);
}
@Override
public boolean onCreate() {
database = new Database(getContext());
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
database.openDb();
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
int uriType =sURIMatcher.match(uri);
switch (uriType) {
case SINGLE_ROW:
String rowID = uri.getPathSegments().get(1);
queryBuilder.appendWhere(KEY_ID + "=" + rowID);
default:
break;
}
queryBuilder.setTables(database.TABLE);
Cursor cursor = queryBuilder.query(database.db, projection, selection,selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
@Override
public String getType(Uri uri) {
switch (sURIMatcher.match(uri)) {
case ALL_ROWS:
return "vnd.android.cursor.dir/vnd.example.elemental";
case SINGLE_ROW:
return "vnd.android.cursor.item/vnd.example.elemental";
default:
throw new IllegalArgumentException("Unsupported URI: " +uri);
}
}
@Override
public Uri insert(Uri uri, ContentValues values) {
database.openDb();
String nullColumnHack = null;
long id = database.db.insert(database.TABLE,nullColumnHack, values);
if (id > -1) {
Uri insertedId = ContentUris.withAppendedId(CONTENT_URI, id);
getContext().getContentResolver().notifyChange(insertedId, null);
return insertedId;
}
else
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
database.openDb();
if (selection == null)
selection = "1";
int deleteCount = database.db.delete(database.TABLE, selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return deleteCount;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
database.openDb();
switch (sURIMatcher.match(uri)) {
case SINGLE_ROW :
String rowID = uri.getPathSegments().get(1);
selection = KEY_ID + "=" + rowID+ (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')': "");
default: break;
}
int updateCount = database.db.update(database.TABLE,values, selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return updateCount;
}
}
Database.java
public class Database extends Activity {
public static final String TAG = "Database";
public static final String C_ID = BaseColumns._ID;
//Columns
public static final String C_NAME = "counterName";
public static final String C_VALUE = "counterValue";
public static final String C_ORDER = "counterOrder";
//Database name, version, table name
public static final String DB_NAME = "list.db";
public static final int DB_VERSION = 1; // If you change, it will call onUpgrade()
public static final String TABLE = "List";
Context context;
DbHelper dbHelper;
SQLiteDatabase db;
public Database(Context context) {
this.context = context;
dbHelper = new DbHelper();
}
class DbHelper extends SQLiteOpenHelper {
public DbHelper() {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql = String.format("CREATE TABLE %s"
+ " (%s INTEGER PRIMARY KEY AUTOINCREMENT, %s VARCHAR, %s INT, %s INT)",
TABLE, C_ID, C_NAME, C_VALUE, C_ORDER);
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists " + TABLE);
onCreate(db);
}
}
public void openDb(){
db=dbHelper.getWritableDatabase();
}
public Cursor query() {
openDb();
// iterate over all rows columns on TABLE
Cursor cursor = db.query(TABLE, null, null, null, null, null, null);
return cursor;
}
}
緩慢部分是'int updatedRowCount = cr.update(MyContentProvider.CONTENT_URI,updatedValues,where,whereArgs);'在MainActivity中調用內容提供者的更新方法。我試着將ContentProvider的更新方法更改爲正常的SQL查詢。仍然很慢,但如果我從MainActivity調用該SQL查詢,那就沒問題。所以我看到LoaderCallbacks工作異步,它在一秒內更新屏幕兩次很慢。 –
我再次使用StartManagingCursor()並且即時快樂:) –
你沒有嘗試像上面提到的那樣使用'AsyncQueryHandler' http://stackoverflow.com/a/13354862/1210272 –