CursorLoader,ContentProvider太慢了

时间:2014-06-30 12:01:23

标签: android android-contentprovider simplecursoradapter android-cursorloader

我有计数器应用,我使用了SimpleCursorAdapterListViewStartManagingCursor()。现在我想使用新的CursorLoaderContentprovider。我编写了自己的ContentProvider并在MainActivity上实现了它。正如你可以看到我上面的应用程序,当我点击加号按钮并更新计数时,它是滞后的。我每秒大约做2次点击,但它无法快速处理。我使用ContentResolver进行更新。

旧方法startManagingCursor很快。

代码就在这里,如果我在ContentProviderCursorLoader上有任何错误,请帮助我。

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;
    }




}

1 个答案:

答案 0 :(得分:0)

我已更改ChannelAdapter,像here那样夸大列表项,我开始使用ViewHolder,这会提高约15-18的速度(我已经从某处读取了) ),findViewById消耗大量时间来查找资源并为每个项目充气。