I wanted to calculate the total price of the products in the cart using SQLite. When I set the price in textview using Settext(), it does not return the sum value. This is the gettotalprice method in DBhelper class.
public int getTotalExpenses()
{
int total = 0;
SQLiteDatabase database = this.getReadableDatabase();
Cursor cursor = database.rawQuery("SELECT SUM("+ OrderContract.OrderEntry.COLUMN_PRICE + ") FROM " + OrderContract.OrderEntry.TABLE_NAME, null);
if (cursor.moveToFirst())
{
total = cursor.getInt(4);
}
while (cursor.moveToNext());
return total;
}
OrderProvider class:
package com.example.myapp;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class OrderProvider extends ContentProvider {
// this constant is needed in order to define the path of our modification in the table
public static final int ORDER=100;
public DBHelper mhelper;
public static UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
sUriMatcher.addURI(OrderContract.CONTENT_AUTHORITY,OrderContract.PATH,ORDER);
}
#Override
public boolean onCreate() {
mhelper = new DBHelper(getContext());
return true;
}
#Override
public Cursor query( Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteDatabase database = mhelper.getReadableDatabase();
Cursor cursor;
int match = sUriMatcher.match(uri);
switch (match){
case ORDER:
cursor = database.query(OrderContract.OrderEntry.TABLE_NAME, projection, selection, selectionArgs, null,null, sortOrder);
break;
default:
throw new IllegalArgumentException("CANT QUERY");
}
cursor.setNotificationUri(getContext().getContentResolver(),uri);
return cursor;
}
#Override
public String getType(Uri uri) {
return null;
}
#Override
public Uri insert(Uri uri, ContentValues values) {
int match = sUriMatcher.match(uri);
switch (match) {
case ORDER:
return insertCart(uri, values);
default:
throw new IllegalArgumentException("Cant insert data");
}
}
private Uri insertCart(Uri uri, ContentValues values) {
String name = values.getAsString(OrderContract.OrderEntry.COLUMN_NAME);
if(name == null){
throw new IllegalArgumentException("Name is Required");
}
String quantity = values.getAsString(OrderContract.OrderEntry.COLUMN_QUANTITY);
if(quantity == null){
throw new IllegalArgumentException("Quantity is Required");
}
String price = values.getAsString(OrderContract.OrderEntry.COLUMN_PRICE);
if(price == null){
throw new IllegalArgumentException("Price is Required");
}
//insert values into order
SQLiteDatabase database = mhelper.getWritableDatabase();
long id = database.insert(OrderContract.OrderEntry.TABLE_NAME, null, values);
if(id == 0){
return null;
}
getContext().getContentResolver().notifyChange(uri,null);
return ContentUris.withAppendedId(uri,id);
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
//delete data once order is made
int rowsDeleted;
SQLiteDatabase database = mhelper.getWritableDatabase();
int match = sUriMatcher.match(uri);
switch (match) {
case ORDER:
rowsDeleted = database.delete(OrderContract.OrderEntry.TABLE_NAME, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Cannot delete");
}
if (rowsDeleted!=0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return rowsDeleted;
}
#Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
}
OrderContract class:
public class OrderContract {
public OrderContract() {
}
//content authority requires package name
public static final String CONTENT_AUTHORITY = "com.example.myapp";
public static final Uri BASE_URI = Uri.parse(("content://" +CONTENT_AUTHORITY));
//same as table name
public static final String PATH = "orders" ;
public static abstract class OrderEntry implements BaseColumns{
public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_URI,PATH);
public static final String TABLE_NAME = "orders" ;
public static final String _ID = BaseColumns._ID ;
public static final String COLUMN_NAME = "name" ;
public static final String COLUMN_QUANTITY = "quantity" ;
public static final String COLUMN_PRICE = "price" ;
}
}
Cart activity:
sofaname=findViewById(R.id.sofaname);
sofaprice=findViewById(R.id.sofaprice);
sofadesc=findViewById(R.id.sofadesc);
plusquantity = findViewById(R.id.addquantity);
minusquantity = findViewById(R.id.subquantity);
quantitynumber = findViewById(R.id.quantity);
addtocart = findViewById(R.id.addtocart);
ImageSlider imageSlider = findViewById(R.id.sofaslider1);
List<SlideModel> slideModels = new ArrayList<>();
slideModels.add(new SlideModel(R.drawable.card14));
slideModels.add(new SlideModel(R.drawable.card6));
slideModels.add(new SlideModel(R.drawable.card7));
imageSlider.setImageList(slideModels,false);
imageSlider.setClickable(false);
DB = new DBHelper(Sofa1.this);
String Name = DB.getProductNamePrice("SELECT F_Name FROM Furniture WHERE F_Type = 'Sofa';");
String Price = DB.getProductNamePrice("SELECT F_Price FROM Furniture WHERE F_Type = 'Sofa';");
String Desc = DB.getProductNamePrice("SELECT F_Description FROM Furniture WHERE F_Type = 'Sofa';");
sofaname.setText(Name);
sofaprice.setText(Price);
sofadesc.setText(Desc);
plusquantity.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(quantity<5){
//sofaprice
int baseprice= Integer.parseInt(sofaprice.getText().toString());
quantity++;
displayquantity();
totalprice = baseprice * quantity;
String setnewprice = (String.valueOf(totalprice));
sofaprice.setText(setnewprice);
}
}
});
minusquantity.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int baseprice=0;
String Price = DB.getProductNamePrice("SELECT F_Price FROM Furniture WHERE F_Type = 'Sofa';");
baseprice = Integer.parseInt(Price);
if(quantity>1) {
quantity--;
displayquantity();
totalprice = baseprice * quantity;
String setnewprice = (String.valueOf(totalprice));
sofaprice.setText(setnewprice);
}
}
});
addtocart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent =new Intent(Sofa1.this,Cart.class);
startActivity(intent);
// once this button is clicked we want to save our values in the database and send those values
// right away to summary activity where we display the order info
SaveCart();
totalamount = (TextView) findViewById(R.id.total);
int totalAmount = DB.getTotalExpenses();
totalamount.setText(String.valueOf(totalAmount));
}
});
}
private boolean SaveCart() {
String name = sofaname.getText().toString();
String price = sofaprice.getText().toString();
String quantity = quantitynumber.getText().toString();
ContentValues values = new ContentValues();
values.put(OrderContract.OrderEntry.COLUMN_NAME,name);
values.put(OrderContract.OrderEntry.COLUMN_PRICE,price);
values.put(OrderContract.OrderEntry.COLUMN_QUANTITY,quantity);
if(mcurrentcarturi == null){
Uri newUri = getContentResolver().insert(OrderContract.OrderEntry.CONTENT_URI, values);
if(newUri == null){
Toast.makeText(this, "Failed to add to cart", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "Product added to cart", Toast.LENGTH_SHORT).show();
}
}
hasallrequiredvalues = true;
return hasallrequiredvalues;
}
private void displayquantity() {
quantitynumber.setText(String.valueOf(quantity));
}
#Override
public #NotNull Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = {OrderContract.OrderEntry._ID,
OrderContract.OrderEntry.COLUMN_NAME,
OrderContract.OrderEntry.COLUMN_PRICE,
OrderContract.OrderEntry.COLUMN_QUANTITY};
return new CursorLoader(this, mcurrentcarturi, projection, null, null, null);
}
#Override
public void onLoadFinished(#NotNull Loader<Cursor> loader, Cursor cursor) {
if(cursor==null || cursor.getCount() < 1){
return;
}
if(cursor.moveToFirst()){
int name = cursor.getColumnIndex(OrderContract.OrderEntry.COLUMN_NAME);
int price = cursor.getColumnIndex(OrderContract.OrderEntry.COLUMN_PRICE);
int quantity = cursor.getColumnIndex(OrderContract.OrderEntry.COLUMN_QUANTITY);
String nameofsofa = cursor.getString(name);
String priceofsofa = cursor.getString(price);
String quantityofsofa = cursor.getString(quantity);
sofaname.setText(nameofsofa);
sofaprice.setText(priceofsofa);
quantitynumber.setText(quantityofsofa);
}
}
#Override
public void onLoaderReset(#NotNull Loader<Cursor> loader) {
sofaname.setText("");
sofaprice.setText("");
quantitynumber.setText("");
}
As your query is effectively
SELECT SUM(price) FROM orders;
Only a single column will be returned, thus using total = cursor.getInt(4); should result in an exception as the column is out of bounds, there will only be 1 column and it's index will be 0.
Thus try changing to use :-
public int getTotalExpenses()
{
int total = 0;
SQLiteDatabase database = this.getReadableDatabase();
Cursor cursor = database.rawQuery("SELECT SUM("+ OrderContract.OrderEntry.COLUMN_PRICE + ") FROM " + OrderContract.OrderEntry.TABLE_NAME, null);
if (cursor.moveToFirst())
{
total = cursor.getInt(0); //<<<<<<<<<< CHANGED
}
//while (cursor.moveToNext()); //<<<<<<<<<< COMMENTED OUT NOT NEEDED
cursor.close(); //<<<<<<<<<< ADDED should always close cursor when finished with them
return total;
}
Related
I am making small app. It has 2 listview on MainActivity.
DB is SQLLite and has tree cloumns id(int), person(text), status(text).
Firt listview will be show informations from DB with this query
select * from DB where status=B
And next ListView will show information where status=A.
lv1.status=b | lv2.status=a
Person 1 | Person 2
Person 3 | Person 4
When i click lv2 on item, value of clicked lv2 field 'status' must change to 'b'.
But I can not write right query for db.
public void changeUser(){
db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_STATUS, "B");
db.update(TABLE_ORDER, values, null, null);
db.close();
}
Thanks
Here is my code
lvB = (ListView)findViewById(R.id.lvB);
listClientB();
lvA = (ListView)findViewById(R.id.lvA);
listClientA();
lvA.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
User user = (User)adapterView.getAdapter().getItem(i);
int id = user.get_id();
if (user.getStatus().contains("A")){
dbHelper.changeUser();
}
Toast.makeText(getApplicationContext(), id + "-NUMBER id", Toast.LENGTH_LONG).show();
Log.d(String.valueOf(user.get_id()), "-NUMBER id");
listClientA();
Log.d(user.getStatus(), "Pressed");
}
});
}
private void listClientA(){
list = dbHelper.allUsersA();
klientStatusAdapter = new KlientStatusAdapter(MainActivity.this, list);
lvA.setAdapter(klientStatusAdapter);
lvA.setTextFilterEnabled(true);
}
private void listClientB(){
list = dbHelper.allUsersB();
klientStatusAdapter = new KlientStatusAdapter(MainActivity.this, list);
lvB.setAdapter(klientStatusAdapter);
lvB.setTextFilterEnabled(true);
}
Here is from DB
public List<User> allUsersA(){
db = this.getReadableDatabase();
List<User> users = new ArrayList<User>();
String s = "select * from " + TABLE_ORDER + " where status = 'A'";
Cursor cursor = db.rawQuery(s, null);
if (cursor.moveToFirst()){
do {
User user = new User();
user.set_id(Integer.parseInt(cursor.getString(0)));
user.setClientName(cursor.getString(1));
user.setCleintOrderedFood(cursor.getString(2));
user.setStatus(cursor.getString(3));
users.add(user);
}while (cursor.moveToNext());
}
db.close();
return users;
}
public List<User> allUsersB(){
db = this.getReadableDatabase();
List<User> users = new ArrayList<User>();
String s = "select * from " + TABLE_ORDER + " where status = 'B'";
Cursor cursor = db.rawQuery(s, null);
if (cursor.moveToFirst()){
do {
User user = new User();
user.set_id(Integer.parseInt(cursor.getString(0)));
user.setClientName(cursor.getString(1));
user.setCleintOrderedFood(cursor.getString(2));
user.setStatus(cursor.getString(3));
users.add(user);
}while (cursor.moveToNext());
}
db.close();
return users;
}
public void changeUser(){
db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_STATUS, "B");
db.update(TABLE_ORDER, values, null, null);
db.close();
}
Here is adapter
public class ClientStatusAdapter extends BaseAdapter{
LayoutInflater inflater;
Context context;
List<User> wordsList;
DbHelper dbHelper;
public ClientStatusAdapter(Context context1, List<User> wordsList) {
this.context = context1;
this.wordsList = wordsList;
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
dbHelper = new DbHelper(context);
}
#Override
public int getCount() {
return wordsList.size();
}
#Override
public Object getItem(int i) {
return wordsList.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
if (view == null){
view = inflater.inflate(R.layout.kliyent_status_adapter, null);
}
TextView txtIsmAdapter = (TextView)view.findViewById(R.id.txtIsmAdapter);
TextView txtOvqatAdapter = (TextView)view.findViewById(R.id.txtOvqatAdapter);
final User user = wordsList.get(i);
TextView txtCliyentNames = (TextView)view.findViewById(R.id.txtCliyentNames);
txtCliyentNames.setText(user.getClientName());
TextView txtCliyentOrderedFoood = (TextView)view.findViewById(R.id.txtCliyentOrderedFoood);
txtCliyentOrderedFoood.setText(user.getCleintOrderedFood());
TextView txtStatusAdapter = (TextView)view.findViewById(R.id.txtStatusAdapter);
txtStatusAdapter.setText(user.getStatus());
notifyDataSetChanged();
ImageView imgOn = (ImageView) view.findViewById(R.id.imgOn);
return view;
}
}
Here is entity User
public class User {
private int _id;
private String clientName;
private String cleintOrderedFood;
private String status = "A";
public User() {
}
public User(int _id, String clientName, String cleintOrderedFood) {
this._id = _id;
this.clientName = clientName;
this.cleintOrderedFood = cleintOrderedFood;
}
public User(int _id, String clientName, String cleintOrderedFood, String status) {
this._id = _id;
this.clientName = clientName;
this.cleintOrderedFood = cleintOrderedFood;
this.status = status;
}
public int get_id() {
return _id;
}
public void set_id(int _id) {
this._id = _id;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public String getCleintOrderedFood() {
return cleintOrderedFood;
}
public void setCleintOrderedFood(String cleintOrderedFood) {
this.cleintOrderedFood = cleintOrderedFood;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
If you look closely at the SQLiteDatabase.update() method, you will see it is declared as
int update (String table,
ContentValues values,
String whereClause,
String[] whereArgs)
Note the last two parameters. These are how you select which rows to update. For example, you can specify to only update rows with a given id:
public void changeUser(int userId){
db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_STATUS, "B");
String whereClause = "_id = ?";
String where = new String[] {Integer.toString(userId)};
db.update(TABLE_ORDER, values, whereClause, where);
db.close();
}
Here I am assuming you use the conventional column name _id. Of course, you can change this to suit your needs if you have a different column name.
Note that you will now need to pass a parameter to changeUser(). However, you have not shown how nor where you currently call it, so I am unable to provide any advice how to change this.
I have two activities MainActivity and Addlogactivity i am updating a data in Addlogactivity which should be displayed in mainactivity recyclerview the data is not updating in database
MianActivityClass :
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor>{
RecyclerView recyclerView;
Intent addDisplay;
Mainrow_Adapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView)findViewById(R.id.listView);
addDisplay = new Intent(this,AddLog.class);
Toolbar toolbar = (Toolbar)findViewById(R.id.maintoolbar);
setSupportActionBar(toolbar);
toolbar.setTitle("Account's");
getSupportLoaderManager().initLoader(1,null,this);
adapter = new Mainrow_Adapter(this,null);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
public void createID(View view)
{
ContentValues values = new ContentValues();
values.put(DataProvider.Pname,"1");
values.put(DataProvider.Pphone,"1");
values.put(DataProvider.Paddress,"1");
values.put(DataProvider.PCategory,"1");
values.put(DataProvider.Pamount,"1");
getContentResolver().insert(DataProvider.ContentUri_Person,values);
long id = DataProvider.insertId;
addDisplay.putExtra("ID",id);
Toast.makeText(MainActivity.this,String.valueOf(id), Toast.LENGTH_SHORT).show();
startActivity(addDisplay);
finish();
}
#Override
protected void onResume() {
super.onResume();
adapter.notifyDataSetChanged();
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] Prjection = {DataProvider.PID,DataProvider.Pname,DataProvider.Pphone,DataProvider.Paddress,DataProvider.PCategory,DataProvider.Pamount};
return new CursorLoader(this,DataProvider.ContentUri_Person,Prjection,null,null,null);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data)
{
adapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader)
{
adapter.swapCursor(null);
}
}
AddLog activity class :
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);
}
}
Content Provider class:
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");
}
Cursor Recyclerview Adapter class:
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
}
}
}
Main Adapter class:
public class Mainrow_Adapter extends CursorRecyclerViewAdapter<Mainrow_Adapter.ViewHolder>
{
public Mainrow_Adapter(Context context, Cursor cursor) {
super(context, cursor);
}
public static class ViewHolder extends RecyclerView.ViewHolder
{
TextView mName,mAmount;
public ViewHolder(View itemView) {
super(itemView);
mName = (TextView)itemView.findViewById(R.id.mainrowname);
mAmount = (TextView)itemView.findViewById(R.id.mainrowAmount);
}
}
#Override
public Mainrow_Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.mainrow_layout,parent,false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(Mainrow_Adapter.ViewHolder viewHolder, Cursor cursor)
{
PersonDetails personDetails = PersonDetails.from(cursor);
viewHolder.mName.setText(personDetails.getName());
viewHolder.mAmount.setText(String.valueOf(personDetails.getAmount()));
}
}
Ok,
then move below three lines from onCreate method to onResume(),
getSupportLoaderManager().initLoader(1,null,this);
adapter = new Mainrow_Adapter(this,null);
recyclerView.setAdapter(adapter);
Hope this will work
I am working on a project where user adds data at runtime.The problem is whenever user inserts the fist element it is adding to the database and displaying in recyclerview.But when user adds more data the recyclerview keeps displaying firstelement over and over again.
If the user adds Apple it is adding to database and recyclerview is displaying Apple.Now if the user adds orange it is adding to database but the recyclerview is displaying Apple two times.
I am using Cursorloader to load data,Contentprovider to add data,and CustomCursoradapter(https://gist.github.com/skyfishjy/443b7448f59be978bc59) to set the data to recyclerview
addDetails() method execute when user adds data
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);
}
}
Content Provider class:
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 class:
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());
}
}
Adapter class :
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());
}
}
Cursor Recyclerview Adapter class:
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
}
}
}
Thank you
Probably from method in Details causing issue due to cursor.moveToFirst(); and do-while loop. change it as:
public static Details from(Cursor cursor)
{
Details details = new Details(cursor.getString(1),
cursor.getDouble(3),
cursor.getString(4));
return details;
}
I have checked your adapter and all, so you are already moving your cursor to particular position from Adapter, so you don't need to set it moveToFist, so just remove the line cursor.moveToFirst() from Details Class and check result.
Anyone knows how to use cursorLoader with DBFlow ? I seen this issue but this is not added to DBFlow.
Thanks.
You can find official docs here or you can implement it the way i have
DBFlow ver used 3
//I have edited my answer & provided easier way for content provider part below
add this to manifest inside application
<provider
android:authorities="com.hashx19.pristinekashmir.mycontentprovider"
android:exported="false"
android:name=".MyContentProvider"/>
Create java file named MyContentProvider & copy below code in it
& replace AUTHORITY ,ENDPOINT, AppDatabase(Your database name) ,TableClassName as per you project.
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.CursorIndexOutOfBoundsException;
import android.net.Uri;
import com.hashx19.pristinekashmir.MySQLiteHelper;
import com.raizlabs.android.dbflow.annotation.ConflictAction;
import com.raizlabs.android.dbflow.config.FlowManager;
import com.raizlabs.android.dbflow.structure.ModelAdapter;
import java.util.Arrays;
import java.util.HashSet;
/**
* Created by Filu on 8/25/2016.
*/
public class MyContentProvider extends ContentProvider {
public static final String AUTHORITY = "com.hashx19.pristinekashmir.mycontentprovider";
private static final String ENDPOOINT = "feeds";
// #ContentUri(path = ENDPOOINT, type = ContentUri.ContentType.VND_MULTIPLE + ENDPOOINT)
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
+ "/" + ENDPOOINT);
private static final int feeds_CONTENT_URI = 0;
private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
static {
MATCHER.addURI(AUTHORITY, ENDPOOINT, feeds_CONTENT_URI);
}
;
#Override
public final String getType(Uri uri) {
String type = null;
switch(MATCHER.match(uri)) {
case feeds_CONTENT_URI: {
type = "vnd.android.cursor.dir/" +ENDPOINT;
break;
}
default: {
throw new IllegalArgumentException("Unknown URI" + uri);
}
}
return type;
}
#Override
public boolean onCreate() {
return false;
}
#Override
public final Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
android.database.Cursor cursor = null;
switch(MATCHER.match(uri)) {
case feeds_CONTENT_URI: {
cursor = FlowManager.getDatabase("AppDatabase").getWritableDatabase().query("TableClassName", projection, selection, selectionArgs, null, null, sortOrder);
break;
}
}
if (cursor != null) {
cursor.setNotificationUri(getContext().getContentResolver(), uri);
}
return cursor;
}
#Override
public final Uri insert(Uri uri, ContentValues values) {
switch(MATCHER.match(uri)) {
case feeds_CONTENT_URI: {
ModelAdapter adapter = FlowManager.getModelAdapter(FlowManager.getTableClassForName("AppDatabase", "TableClassName"));
final long id = FlowManager.getDatabase("AppDatabase").getWritableDatabase().insertWithOnConflict("TableClassName", null, values, ConflictAction.getSQLiteDatabaseAlgorithmInt(adapter.getInsertOnConflictAction()));
getContext().getContentResolver().notifyChange(uri, null);
return ContentUris.withAppendedId(uri, id);
}
default: {
throw new IllegalStateException("Unknown Uri" + uri);
}
}
}
#Override
public final int delete(Uri uri, String selection, String[] selectionArgs) {
switch(MATCHER.match(uri)) {
case feeds_CONTENT_URI: {
long count = FlowManager.getDatabase("AppDatabase").getWritableDatabase().delete("TableClassName", selection, selectionArgs);
if (count > 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return (int) count;
}
default: {
throw new IllegalArgumentException("Unknown URI" + uri);
}
}
}
#Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
switch(MATCHER.match(uri)) {
case feeds_CONTENT_URI: {
ModelAdapter adapter = FlowManager.getModelAdapter(FlowManager.getTableClassForName("AppDatabase", "TableClassName"));
long count = FlowManager.getDatabase("AppDatabase").getWritableDatabase().updateWithOnConflict("TableClassName", values, selection, selectionArgs, ConflictAction.getSQLiteDatabaseAlgorithmInt(adapter.getUpdateOnConflictAction()));
if (count > 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return (int) count;
}
default: {
throw new IllegalStateException("Unknown Uri" + uri);
}
}
}
}
then when overriding Loader methods do something like this
getLoaderManager().initLoader(1, null, this);
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String selection, sortOrder;
String[] selectionArgs, projection;
selection = ...;
selectionArgs = ...;
sortOrder = ...;
projection= new String[]{"id","date", "link","title","content","excerpt","author",};
CursorLoader cursorLoader = new CursorLoader(getContext(),MyContentProvider.CONTENT_URI, projection,null,null,null);
return cursorLoader;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
TableClass post = new TableClass();
while (!cursor.isAfterLast()) {
try{
post.setId(cursor.getInt(cursor.getColumnIndex("id")));
}catch (NullPointerException e){
e.printStackTrace();
}catch (CursorIndexOutOfBoundsException c){
c.printStackTrace();
}
}
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
}
editted
Figured out easier way to implement content provider .
add this to your manifest / or modify this way if you already have added Provider code .
modify your AppDatabase Class as
#ContentProvider(authority = AppDatabase.AUTHORITY,
database = AppDatabase.class,
baseContentUri = AppDatabase.BASE_CONTENT_URI)
#Database(name = AppDatabase.NAME, version = AppDatabase.VERSION)
public class AppDatabase {
public static final String NAME = "AppDatabase"; // we will add the .db extension
public static final int VERSION = 2;
public static final String AUTHORITY = "com.hashx19.pristinekashmir.dbflowcontentprovider";
public static final String BASE_CONTENT_URI = "content://"; }
modify each table you want to use as provider as
#TableEndpoint(name = PostData.ENDPOINT, contentProvider = AppDatabase.class)
#Table(database = AppDatabase.class ,allFields = true ,name = PostData.ENDPOINT)
public class PostData extends BaseModel {
public static final String ENDPOINT = "PostData";
#ContentUri(path = ENDPOINT, type = ContentUri.ContentType.VND_MULTIPLE + ENDPOINT)
public static final Uri CONTENT_URI = Uri.parse(AppDatabase.BASE_CONTENT_URI + AppDatabase.AUTHORITY
+ "/" + ENDPOINT);
#PrimaryKey
public int id;
public String image;
}
For using Content provider as in Cursor Loader use TableName.CONTENT_URI as in this case
CursorLoader cursorLoader = new CursorLoader(getContext(),PostData.CONTENT_URI,projection,null,null,null);
I have followed the below tutorial http://www.vogella.de/articles/AndroidSQLite/article.htm
But getting this exception after clicking on "confirm" button
01-20 10:18:14.585: E/AndroidRuntime(2006): Caused by: java.lang.IllegalArgumentException: Unknown URL content://com.example.todos.contentprovider/todos
01-20 10:18:14.585: E/AndroidRuntime(2006): at android.content.ContentResolver.insert(ContentResolver.java:910)
01-20 10:18:14.585: E/AndroidRuntime(2006): at com.example.todos.TodoDetailActivity.saveState(TodoDetailActivity.java:122)
01-20 10:18:14.585: E/AndroidRuntime(2006): at com.example.todos.TodoDetailActivity.onPause(TodoDetailActivity.java:100)
TodoDetailActivity
public class TodoDetailActivity extends Activity {
private Spinner mCategory;
private EditText mTitleText;
private EditText mBodyText;
private Uri todoUri;
#Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.todo_edit);
mCategory = (Spinner) findViewById(R.id.category);
mTitleText = (EditText) findViewById(R.id.todo_edit_summary);
mBodyText = (EditText) findViewById(R.id.todo_edit_description);
Button confirmButton = (Button) findViewById(R.id.todo_edit_button);
Bundle extras = getIntent().getExtras();
// check from the saved Instance
todoUri = (bundle == null) ? null : (Uri) bundle
.getParcelable(MyTodoContentProvider.CONTENT_ITEM_TYPE);
// Or passed from the other activity
if (extras != null) {
todoUri = extras
.getParcelable(MyTodoContentProvider.CONTENT_ITEM_TYPE);
fillData(todoUri);
}
confirmButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if (TextUtils.isEmpty(mTitleText.getText().toString())) {
makeToast();
} else {
setResult(RESULT_OK);
finish();
}
}
});
}
private void fillData(Uri uri) {
String[] projection = { TodoTable.COLUMN_SUMMARY,
TodoTable.COLUMN_DESCRIPTION, TodoTable.COLUMN_CATEGORY };
Cursor cursor = getContentResolver().query(uri, projection, null, null,
null);
if (cursor != null) {
cursor.moveToFirst();
String category = cursor.getString(cursor
.getColumnIndexOrThrow(TodoTable.COLUMN_CATEGORY));
for (int i = 0; i < mCategory.getCount(); i++) {
String s = (String) mCategory.getItemAtPosition(i);
if (s.equalsIgnoreCase(category)) {
mCategory.setSelection(i);
}
}
mTitleText.setText(cursor.getString(cursor
.getColumnIndexOrThrow(TodoTable.COLUMN_SUMMARY)));
mBodyText.setText(cursor.getString(cursor
.getColumnIndexOrThrow(TodoTable.COLUMN_DESCRIPTION)));
// always close the cursor
cursor.close();
}
}
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
saveState();
outState.putParcelable(MyTodoContentProvider.CONTENT_ITEM_TYPE, todoUri);
}
#Override
protected void onPause() {
super.onPause();
saveState();
}
private void saveState() {
String category = (String) mCategory.getSelectedItem();
String summary = mTitleText.getText().toString();
String description = mBodyText.getText().toString();
// only save if either summary or description
// is available
if (description.length() == 0 && summary.length() == 0) {
return;
}
ContentValues values = new ContentValues();
values.put(TodoTable.COLUMN_CATEGORY, category);
values.put(TodoTable.COLUMN_SUMMARY, summary);
values.put(TodoTable.COLUMN_DESCRIPTION, description);
if (todoUri == null) {
// New todo
todoUri = getContentResolver().insert(
MyTodoContentProvider.CONTENT_URI, values);
} else {
// Update todo
getContentResolver().update(todoUri, values, null, null);
}
}
private void makeToast() {
Toast.makeText(TodoDetailActivity.this, "Please maintain a summary",
Toast.LENGTH_LONG).show();
}
}
MyTodoContentProvider
public class MyTodoContentProvider extends ContentProvider{
//database
private TodoDatabaseHelper database;
//Used for the uriMatcher
private static final int TODOS = 10;
private static final int TODO_ID = 20;
private static final String AUTHORITY = "com.example.todos.contentprovider";
private static final String BASE_PATH = "todos";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY+ "/" + BASE_PATH);
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, TODOS);
sURIMatcher.addURI(AUTHORITY, BASE_PATH + "/#", TODO_ID);
}
#Override
public boolean onCreate()
{
database = new TodoDatabaseHelper(getContext());
return false;
}
#Override
public Cursor query(Uri uri,String[] projection, String selection,
String[] selectionArgs, String sortOrder)
{
// Uisng SQLiteQueryBuilder instead of query() method
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
// check if the caller has requested a column which does not exists
checkColumns(projection);
//set the table
queryBuilder.setTables(TodoTable.TABLE_TODO);
int uriType = sURIMatcher.match(uri);
switch (uriType) {
case TODOS:
break;
case TODO_ID:
// adding the ID to the original query
queryBuilder.appendWhere(TodoTable.COLUMN_ID + "="
+ uri.getLastPathSegment());
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
SQLiteDatabase db = database.getWritableDatabase();
Cursor cursor = queryBuilder.query(db, projection, selection,
selectionArgs, null, null, sortOrder);
// make sure that potential listeners are getting notified
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 sqlDB = database.getWritableDatabase();
long id = 0;
switch (uriType) {
case TODOS:
id = sqlDB.insert(TodoTable.TABLE_TODO, null, values);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return Uri.parse(BASE_PATH + "/" + id);
}
#Override
public int delete(Uri uri, String selection,String[] selectionArgs)
{
int uriType = sURIMatcher.match(uri);
SQLiteDatabase sqlDB = database.getWritableDatabase();
int rowsDeleted = 0;
switch (uriType) {
case TODOS:
rowsDeleted = sqlDB.delete(TodoTable.TABLE_TODO,selection, selectionArgs);
break;
case TODO_ID:
String id = uri.getLastPathSegment();
if(TextUtils.isEmpty(selection))
{
rowsDeleted = sqlDB.delete(TodoTable.TABLE_TODO,TodoTable.COLUMN_ID + "=" + id,null);
}
else
{
rowsDeleted = sqlDB.delete(TodoTable.TABLE_TODO,TodoTable.COLUMN_ID + "=" + id + "and" + selection ,selectionArgs);
}
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 = 0;
switch (uriType) {
case TODOS:
rowsUpdated = sqlDb.update(TodoTable.TABLE_TODO, values, selection, selectionArgs);
break;
case TODO_ID:
String id = uri.getLastPathSegment();
if(TextUtils.isEmpty(selection))
{
rowsUpdated = sqlDb.update(TodoTable.TABLE_TODO, values, TodoTable.COLUMN_ID + "=" + id, null);
}
else
{
rowsUpdated = sqlDb.update(TodoTable.TABLE_TODO, values, TodoTable.COLUMN_ID + "=" + id + "and" + selection, selectionArgs);
}
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsUpdated;
}
private void checkColumns(String[] projection)
{
String[] available = {TodoTable.COLUMN_CATEGORY,TodoTable.COLUMN_SUMMARY,TodoTable.COLUMN_DESCRIPTION,TodoTable.COLUMN_ID};
HashSet<String> requestedColumns = new HashSet<String>(Arrays.asList(projection));
HashSet<String> availableColumns = new HashSet<String>(Arrays.asList(available));
if(projection != null)
{
if (!availableColumns.containsAll(requestedColumns)) {
throw new IllegalArgumentException("Unknown columns in projection");
}
}
}
}
TodoDatabaseHelper
public class TodoDatabaseHelper extends SQLiteOpenHelper{
private static final String DATABASE_NAME = "todotable.db";
private static final int DATABASE_VERSION = 1;
public TodoDatabaseHelper(Context context)
{
super(context,DATABASE_NAME,null,DATABASE_VERSION);
}
//Method is called during creation of database
#Override
public void onCreate(SQLiteDatabase database)
{
TodoTable.onCreate(database);
}
// Method is called during an upgrade of the database,
// e.g. if you increase the database version
#Override
public void onUpgrade(SQLiteDatabase database, int oldVersion,
int newVersion) {
TodoTable.onUpgrade(database, oldVersion, newVersion);
}
}
You are using
private static final String AUTHORITY = "com.example.todos.contentprovider";
// It should same as you defined in manifest
So this
Caused by: java.lang.IllegalArgumentException: Unknown URL content://com.example.todos.contentprovider/todos
So make sure you define your ContentProvider with same authority in manifest.xml
<provider
android:authorities="com.example.todos.contentprovider"
android:name=".YOUR_ContentProvider" >
</provider>
Hope this will work for you.
Also ensure that you give android:exported="true" in manifest.xml, also ensure they are placed inside </application> not inside </activity>.
<provider
android:name="com.example.todos.contentprovider"
android:authorities="com.example.todos.contentprovider.MyTodoContentProvider"
android:exported="true">
</provider>