0

我正在处理用户在运行时添加数据的项目。问题是每当用户插入将其添加到数据库并在recyclerview中显示的第一个元素时。但是当用户添加更多数据时,recyclerview会一直显示第一个元素一遍又一遍地。 如果用户添加Apple它将添加到数据库并且recyclerview显示Apple。现在如果用户添加orange它将添加到数据库,但回收站视图显示Apple两次。 我使用Cursorloader加载数据,ContentProvider的添加数据,并且CustomCursoradapter(https://gist.github.com/skyfishjy/443b7448f59be978bc59)设置数据到recyclerview当用户将数据Recyclerview不刷新

addDetails()方法执行

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

    TextView TotalAmount,Date; 
    EditText name,mobile,city,detailname,detailamount; 
    RecyclerView adddetailtolist; 
    DetailsAdapter adapter; 
    Intent returnback; 
    double totamount; 
    long logid; 
    String Debt = "Debt"; 
    String Paid = "Paid"; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_add_log); 
     Toolbar toolbar = (Toolbar)findViewById(R.id.addlogtoolbar); 
     setSupportActionBar(toolbar); 
     toolbar.setTitle("Add Log"); 
     returnback = new Intent(this,MainActivity.class); 
     Intent intent = getIntent(); 
     logid = intent.getExtras().getLong("ID"); 
     TotalAmount = (TextView)findViewById(R.id.totalAmount); 
     Date = (TextView)findViewById(R.id.addlogDate); 
     name = (EditText)findViewById(R.id.AddName); 
     mobile = (EditText)findViewById(R.id.AddPhone); 
     city = (EditText)findViewById(R.id.Addcity); 
     detailname = (EditText)findViewById(R.id.Detailname); 
     detailamount = (EditText)findViewById(R.id.Detailamount); 
     adddetailtolist = (RecyclerView)findViewById(R.id.addloglist); 
     Date.setText(getDate()); 
     getSupportLoaderManager().initLoader(1,null,this); 
     adapter = new DetailsAdapter(this,null); 
     adddetailtolist.setAdapter(adapter); 
     adddetailtolist.setLayoutManager(new LinearLayoutManager(this)); 

    } 
    private String getDate() 
    { 
     Calendar calendar = Calendar.getInstance(); 
     SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE,dd-MMM-yyyy"); 
     String date = simpleDateFormat.format(calendar.getTime()); 
     return date; 
    } 
    public void addDetails(View view) 
    { 
     String Name = detailname.getText().toString(); 
     String Amount = detailamount.getText().toString(); 
     String date = Date.getText().toString(); 
     ContentValues contentValues = new ContentValues(); 
     contentValues.put(DataProvider.Dname,Name); 
     contentValues.put(DataProvider.DCategory,Debt); 
     contentValues.put(DataProvider.Damount,Amount); 
     contentValues.put(DataProvider.Ddate,date); 
     contentValues.put(DataProvider.Per_In,logid); 
     Uri uri = getContentResolver().insert(DataProvider.ContentUri_Details,contentValues); 
     Toast.makeText(AddLog.this, uri.toString()+"Value Inserted", Toast.LENGTH_SHORT).show(); 
     NumberFormat currency = changeamount(); 
     TotalAmount.setText(currency.format(getAmount())); 
    } 

    private double getAmount() 
    { 
     ContentProviderClient client = getContentResolver().acquireContentProviderClient(DataProvider.ContentUri_Details); 
     SQLiteDatabase db = ((DataProvider)client.getLocalContentProvider()).sqLiteDatabase; 
     String query = "SELECT SUM(DAmount) FROM Details WHERE Per_In = "+logid; 
     Cursor cursor = db.rawQuery(query, null); 
     cursor.moveToFirst(); 
     double amount = cursor.getDouble(0); 
     cursor.close(); 
     client.release(); 
     return amount; 
    } 


    public NumberFormat changeamount() 
    { 
     Locale locale = new Locale("en","IN"); 
     NumberFormat currencyformat = NumberFormat.getCurrencyInstance(locale); 
     return currencyformat; 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     MenuInflater menuinflate = getMenuInflater(); 
     menuinflate.inflate(R.menu.addlogmenu,menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) 
    { 
     switch (item.getItemId()) 
     { 
      case R.id.done: 
       saveData(); 
     } 
     return super.onOptionsItemSelected(item); 
    } 

    private void saveData() 
    { 
     String name1 = name.getText().toString(); 
     String phone = mobile.getText().toString(); 
     String address = city.getText().toString(); 
     if (TextUtils.isEmpty(name1)||TextUtils.isEmpty(phone)||TextUtils.isEmpty(address)) 
     { 
      if (TextUtils.isEmpty(name1)) 
      { 
       name.setError("Feild can not be Empty"); 
      } 
      else if (TextUtils.isEmpty(phone)) 
      { 
       mobile.setError("Feild can not be Empty"); 
      } 
      else if (TextUtils.isEmpty(address)) 
      { 
       city.setError("Feild can not be Empty"); 
      } 
     } 
     else 
     { 
      ContentValues values = new ContentValues(); 
      values.put(DataProvider.Pname,name1); 
      values.put(DataProvider.Pphone,phone); 
      values.put(DataProvider.Paddress,address); 
      values.put(DataProvider.PCategory,"Debt"); 
      values.put(DataProvider.Pamount,totamount); 
      String where = DataProvider.PID+"=?"; 
      String[] whereargs = {String.valueOf(logid)}; 
      int a = getContentResolver().update(DataProvider.ContentUri_Person,values,where,whereargs); 
      Toast.makeText(AddLog.this, String.valueOf(1)+"Value updated", Toast.LENGTH_SHORT).show(); 
      startActivity(returnback); 
      finish(); 
     } 
    } 

    @Override 
    public Loader<Cursor> onCreateLoader(final int id, Bundle args) 
    { 
     String[] Projection = new String[]{DataProvider.DID,DataProvider.Dname,DataProvider.DCategory,DataProvider.Damount,DataProvider.Ddate}; 
     String selection = DataProvider.Per_In+"=?"; 
     String[] selectionargs = new String[]{String.valueOf(logid)}; 
     return new CursorLoader(this,DataProvider.ContentUri_Details,Projection,selection,selectionargs,null); 
    } 

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

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

内容提供者类:

public class DataProvider extends ContentProvider 
{ 
    static final String ProviderName = "com.example.mrudu.accounts.provider"; 
    static final String URLPerson = "content://"+ProviderName+"/Person_Detail"; 
    static final String URLDetails = "content://"+ProviderName+"/Details"; 
    static final Uri ContentUri_Person = Uri.parse(URLPerson); 
    static final Uri ContentUri_Details = Uri.parse(URLDetails); 
//Tables 
private static String PTableName = "Person_Detail"; 
private static String DTableName = "Details"; 

public static long insertId = 0; 

//Person_Detail Coloumns 
public static String PID = "_id"; 
public static String Pname = "PName"; 
public static String Pphone = "PMobile"; 
public static String Paddress = "PCity"; 
public static String PCategory = "PCategory"; 
public static String Pamount = "PAmount"; 

//Details coloumn 
public static String DID = "_id"; 
public static String Dname = "DName"; 
public static String Damount = "DAmount"; 
public static String Ddate = "DDate"; 
public static String DCategory = "DCategory"; 
public static String Per_In = "Per_In"; 

private static final int Person = 1; 
private static final int Person_ID = 2; 
private static final int Details = 3; 
private static final int Details_Id = 4; 

static UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 
static 
{ 
    uriMatcher.addURI(ProviderName,PTableName,Person); 
    uriMatcher.addURI(ProviderName,PTableName+"/#",Person_ID); 
    uriMatcher.addURI(ProviderName,DTableName,Details); 
    uriMatcher.addURI(ProviderName,DTableName+"/#",Details_Id); 
} 

public static SQLiteDatabase sqLiteDatabase; 
private static String Databasename = "Accounts"; 
private static int DatabaseVersion = 1; 

private class DatabaseHelper extends SQLiteOpenHelper 
{ 

    public DatabaseHelper(Context context) 
    { 
     super(context, Databasename, null, DatabaseVersion); 
    } 

    @Override 
    public void onCreate(SQLiteDatabase sqLiteDatabase) 
    { 
     String Create_Person = " Create Table "+PTableName+"("+PID+" INTEGER PRIMARYKEY ,"+Pname+" TEXT ,"+Pphone+" TEXT ,"+Paddress+" TEXT ,"+PCategory+" TEXT ,"+Pamount+" REAL"+")"; 
     String Create_Details = " Create Table "+DTableName+"("+DID+" INTEGER PRIMARYKEY ,"+Dname+" TEXT ,"+DCategory+" TEXT ,"+Damount+" REAl ,"+Ddate+" TEXT ,"+Per_In+" INTEGER)"; 
     sqLiteDatabase.execSQL(Create_Person); 
     sqLiteDatabase.execSQL(Create_Details); 
    } 

    @Override 
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) 
    { 
     sqLiteDatabase.execSQL("Drop TABLE if exists"+PTableName); 
     sqLiteDatabase.execSQL("Drop TABLE if exists"+DTableName); 
     onCreate(sqLiteDatabase); 
    } 
} 
@Override 
public boolean onCreate() 
{ 
    Context context = getContext(); 
    DatabaseHelper databaseHelper = new DatabaseHelper(context); 
    sqLiteDatabase = databaseHelper.getWritableDatabase(); 
    return (sqLiteDatabase==null)?false:true; 
} 
@Override 
public Uri insert(Uri uri, ContentValues values) 
{ 
    switch (uriMatcher.match(uri)) 
    { 
     case Person: 
      long rowId = sqLiteDatabase.insert(PTableName,null,values); 
      insertId = rowId; 
      if (rowId>0) 
      { 
       Uri _uri = ContentUris.withAppendedId(ContentUri_Person,rowId); 
       getContext().getContentResolver().notifyChange(_uri,null); 
       return _uri; 
      } 
      break; 
     case Details: 
      long rowId1 = sqLiteDatabase.insert(DTableName,null,values); 
      if (rowId1>0) 
      { 
       Uri _uri = ContentUris.withAppendedId(ContentUri_Details,rowId1); 
       getContext().getContentResolver().notifyChange(_uri,null); 
       return _uri; 
      } 
      break; 
    } 
    return null; 
} 
@Override 
public Cursor query(Uri uri, String[] projection, String selection, 
        String[] selectionArgs, String sortOrder) 
{ 
    SQLiteQueryBuilder sqLiteQueryBuilder = new SQLiteQueryBuilder(); 

    switch (uriMatcher.match(uri)) 
    { 
     case Person_ID: 
      sqLiteQueryBuilder.setTables(PTableName); 
      sqLiteQueryBuilder.appendWhere(PID+ "="+ uri.getPathSegments().get(1)); 
      break; 
     case Person: 
      sqLiteQueryBuilder.setTables(PTableName); 
      break; 
     case Details_Id: 
      sqLiteQueryBuilder.setTables(DTableName); 
      sqLiteQueryBuilder.appendWhere(Per_In +"="+ uri.getPathSegments().get(1)); 
      break; 
     case Details: 
      sqLiteQueryBuilder.setTables(DTableName); 
      break; 
     default: 
      throw new UnsupportedOperationException("Not yet implemented"); 
    } 
    Cursor cursor = sqLiteQueryBuilder.query(sqLiteDatabase,projection,selection,selectionArgs,null,null,sortOrder); 
    cursor.setNotificationUri(getContext().getContentResolver(),uri); 
    return cursor; 

} 
@Override 
public int update(Uri uri, ContentValues values, String selection, 
        String[] selectionArgs) 
{ 
    int count = 0; 
    switch (uriMatcher.match(uri)) 
    { 
     case Person: 
      count = sqLiteDatabase.update(PTableName,values,selection,selectionArgs); 
      break; 
     case Person_ID: 
      count = sqLiteDatabase.update(PTableName,values,PID+" = "+uri.getPathSegments().get(1)+(!TextUtils.isEmpty(selection)?" AND (" + selection + ')':""),selectionArgs); 
      break; 
     case Details: 
      count = sqLiteDatabase.update(DTableName,values,selection,selectionArgs); 
      break; 
     case Details_Id: 
      count = sqLiteDatabase.update(DTableName,values,Per_In+" = "+uri.getPathSegments().get(1)+(!TextUtils.isEmpty(selection)?" AND (" + selection + ')':""),selectionArgs); 
      break; 
     default: 
      throw new IllegalArgumentException("Unknown URI " + uri); 
    } 
    getContext().getContentResolver().notifyChange(uri,null); 
    return count; 
} 
@Override 
public int delete(Uri uri, String selection, String[] selectionArgs) { 
    // Implement this to handle requests to delete one or more rows. 
    throw new UnsupportedOperationException("Not yet implemented"); 
} 

@Override 
public String getType(Uri uri) { 
    // TODO: Implement this to handle requests for the MIME type of the data 
    // at the given URI. 
    throw new UnsupportedOperationException("Not yet implemented"); 
} 

}

Detils类:

public class Details 
{ 
    String name,date; 
    double amount; 

    public Details(String name, double amount, String date) { 
     this.name = name; 
     this.amount = amount; 
     this.date = date; 
    } 

    public Details() { 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public double getAmount() { 
     return amount; 
    } 

    public void setAmount(double amount) { 
     this.amount = amount; 
    } 

    public String getDate() { 
     return date; 
    } 

    public void setDate(String date) { 
     this.date = date; 
    } 

    public static Details from(Cursor cursor) 
    { 
     cursor.moveToFirst(); 
     do { 
      Details details = new Details(cursor.getString(1),cursor.getDouble(3),cursor.getString(4)); 
      return details; 
     }while (cursor.moveToNext()); 
    } 
} 

适配器类:

public class DetailsAdapter extends CursorRecyclerViewAdapter<DetailsAdapter.View_Holder> 
{ 

    public DetailsAdapter(Context context, Cursor cursor) { 
     super(context, cursor); 
    } 
    public static class View_Holder extends RecyclerView.ViewHolder 
    { 
     TextView mName,mAmount,mDate; 
     public View_Holder(View itemView) 
     { 
      super(itemView); 
      mName = (TextView)itemView.findViewById(R.id.DetailName); 
      mAmount = (TextView)itemView.findViewById(R.id.DetailAmount); 
      mDate = (TextView)itemView.findViewById(R.id.DetailDate); 
     } 
    } 
    @Override 
    public DetailsAdapter.View_Holder onCreateViewHolder(ViewGroup parent, int viewType) 
    { 
     View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.addloglistlayout,parent,false); 
     View_Holder viewHolder = new View_Holder(view); 
     return viewHolder; 
    } 

    @Override 
    public void onBindViewHolder(DetailsAdapter.View_Holder viewHolder, Cursor cursor) 
    { 
     Details details = Details.from(cursor); 
     viewHolder.mName.setText(details.getName()); 
     viewHolder.mAmount.setText(String.valueOf(details.getAmount())); 
     viewHolder.mDate.setText(details.getDate()); 
    } 
} 

光标Recyclerview适配器类:

public abstract class CursorRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> { 
    private Context mContext; 

    private Cursor mCursor; 

    private boolean mDataValid; 

    private int mRowIdColumn; 

    private DataSetObserver mDataSetObserver; 

    public CursorRecyclerViewAdapter(Context context, Cursor cursor) { 
     mContext = context; 
     mCursor = cursor; 
     mDataValid = cursor != null; 
     mRowIdColumn = mDataValid ? mCursor.getColumnIndex("_id") : -1; 
     mDataSetObserver = new NotifyingDataSetObserver(); 
     if (mCursor != null) { 
      mCursor.registerDataSetObserver(mDataSetObserver); 
     } 
    } 

    public Cursor getCursor() { 
     return mCursor; 
    } 

    @Override 
    public int getItemCount() { 
     if (mDataValid && mCursor != null) { 
      return mCursor.getCount(); 
     } 
     return 0; 
    } 

    @Override 
    public long getItemId(int position) { 
     if (mDataValid && mCursor != null && mCursor.moveToPosition(position)) { 
      return mCursor.getLong(mRowIdColumn); 
     } 
     return 0; 
    } 

    @Override 
    public void setHasStableIds(boolean hasStableIds) { 
     super.setHasStableIds(true); 
    } 

    public abstract void onBindViewHolder(VH viewHolder, Cursor cursor); 

    @Override 
    public void onBindViewHolder(VH viewHolder, int position) { 
     if (!mDataValid) { 
      throw new IllegalStateException("this should only be called when the cursor is valid"); 
     } 
     if (!mCursor.moveToPosition(position)) { 
      throw new IllegalStateException("couldn't move cursor to position " + position); 
     } 
     onBindViewHolder(viewHolder, mCursor); 
    } 

    /** 
    * Change the underlying cursor to a new cursor. If there is an existing cursor it will be 
    * closed. 
    */ 
    public void changeCursor(Cursor cursor) { 
     Cursor old = swapCursor(cursor); 
     if (old != null) { 
      old.close(); 
     } 
    } 

    /** 
    * Swap in a new Cursor, returning the old Cursor. Unlike 
    * {@link #changeCursor(Cursor)}, the returned old Cursor is <em>not</em> 
    * closed. 
    */ 
    public Cursor swapCursor(Cursor newCursor) { 
     if (newCursor == mCursor) { 
      return null; 
     } 
     final Cursor oldCursor = mCursor; 
     if (oldCursor != null && mDataSetObserver != null) { 
      oldCursor.unregisterDataSetObserver(mDataSetObserver); 
     } 
     mCursor = newCursor; 
     if (mCursor != null) { 
      if (mDataSetObserver != null) { 
       mCursor.registerDataSetObserver(mDataSetObserver); 
      } 
      mRowIdColumn = newCursor.getColumnIndexOrThrow("_id"); 
      mDataValid = true; 
      notifyDataSetChanged(); 
     } else { 
      mRowIdColumn = -1; 
      mDataValid = false; 
      notifyDataSetChanged(); 
      //There is no notifyDataSetInvalidated() method in RecyclerView.Adapter 
     } 
     return oldCursor; 
    } 

    private class NotifyingDataSetObserver extends DataSetObserver { 
     @Override 
     public void onChanged() { 
      super.onChanged(); 
      mDataValid = true; 
      notifyDataSetChanged(); 
     } 

     @Override 
     public void onInvalidated() { 
      super.onInvalidated(); 
      mDataValid = false; 
      notifyDataSetChanged(); 
      //There is no notifyDataSetInvalidated() method in RecyclerView.Adapter 
     } 
    } 
} 

谢谢

+0

你能告诉我你的CursorRecyclerViewAdapter类代码吗? – Vickyexpert

+0

@Vickyexpert我只是把它添加到问题 –

+0

检查我的答案 – Vickyexpert

回答

1

大概from方法Details造成的问题,由于cursor.moveToFirst();do-while循环。更改为:

public static Details from(Cursor cursor) 
    { 
     Details details = new Details(cursor.getString(1), 
            cursor.getDouble(3), 
            cursor.getString(4)); 
     return details; 
    } 
+0

感谢man..It工作。但我有另一个问题正如你可以在代码中看到我有两个活动'MainActivity'和'Addlogactivity'我正在更新数据在应该显示在'mainactivity' recyclerview中的'Addlogactivity'中,数据在数据库中更新,但mainactivity recyclerview中的值不变。请帮助我解决这个问题。 –

+0

@MallisettiMrudhuhas:好的,但不是让这个问题太大,我建议你为下一期的相关代码包括MainActivity代码提出一个新问题。并与我共享链接我一定会尝试帮助 –

+0

这里是链接..http://stackoverflow.com/questions/37475854/recyclerview-not-updating-data-from-another-activity –

1

我检查你的适配器和所有的,所以你已经从适配器移动光标到特定位置,所以你不需要moveToFist设置它,所以只是删除线光标。 moveToFirst()从Details Class中检查结果。

+0

解决它谢谢人 –

+0

不是一个问题享受你的代码 – Vickyexpert

+0

我有另一个问题正如你可以在代码中看到我有两个活动MainActivity和Addlogactivity我正在更新Addlogactivity中的数据应显示在mainactivity recyclerview数据在数据库中更新,但主活动recyclerview没有改变。请你也可以帮助我。我可以问这是另一个问题。但它是说我必须在90分钟后问问题 –