1

我有計數器應用程序,我已經使用SimpleCursorAdapter,ListViewStartManagingCursor()。現在我想用新的CursorLoaderContentprovider。我寫了我自己的ContentProvider並在MainActivity上實現。正如你上面看到我的應用程序,當我點擊加號按鈕並更新計數時,它是滯後的。我每秒做大約2次點擊,但無法快速處理。我使用ContentResolver進行更新。CursorLoader,ContentProvider太慢了

老辦法,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; 
    } 




} 
+0

緩慢部分是'int updatedRowCount = cr.update(MyContentProvider.CONTENT_URI,updatedValues,where,whereArgs);'在MainActivity中調用內容提供者的更新方法。我試着將ContentProvider的更新方法更改爲正常的SQL查詢。仍然很慢,但如果我從MainActivity調用該SQL查詢,那就沒問題。所以我看到LoaderCallbacks 工作異步,它在一秒內更新屏幕兩次很慢。 –

+0

我再次使用StartManagingCursor()並且即時快樂:) –

+0

你沒有嘗試像上面提到的那樣使用'AsyncQueryHandler' http://stackoverflow.com/a/13354862/1210272 –

回答

0

我已經改變ChannelAdapter,膨脹列出項目像here,我開始使用ViewHolder,這會增加約15-18%的速度(我已經從某處讀取),findViewById消耗大量時間來查找資源並使每個項目膨脹。