Android Using a Thread to Execute SQLite Queries - java

I am trying to create a database of restaurants and their items for an app as a starter project to get familiar with android. I have a list from a previous activity where a user clicks on the name of the restaurant and the items are shown. I created a helperDB class to handle the insert statements and database setup, although when I called my insert method from inside a new thread, they do not seem to execute. I have provided the code below:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_bar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent intent = getIntent();
String barName = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
final TextView tv = (TextView) findViewById(R.id.name);
tv.setText(barName);
restaurants = new ArrayList<String>();
mydb = new DBHelper(this);
new Thread(new Runnable() {
#Override
public void run() {
mydb.insertDrink("cake", "McD's", 8);
mydb.insertDrink("muffin", "The Woods", 8);
restaurants = mydb.getDrinks("The Woods");
System.out.println(restaurants);
}
}).start();
ArrayAdapter arrayAdapter=new ArrayAdapter(this,android.R.layout.simple_list_item_1, restaurants);
obj = (ListView)findViewById(R.id.listview);
obj.setAdapter(arrayAdapter);
}
The code for the insert statement and getDrinks method are as follows:
public boolean insertDrink(String drink, String name, int price){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("drink", drink);
contentValues.put("name", name);
contentValues.put("price", price);
db.insert("Bars", null, contentValues);
return true;
}
public ArrayList<String> getDrinks(String name){
ArrayList<String> arrayList = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery("select * from Bars", null);
res.moveToFirst();
while(res.isAfterLast() == false){
arrayList.add(res.getString(res.getColumnIndex(BAR_COLUMN_DRINK)));
res.moveToNext();
}
return arrayList;
}
I know that I am not supposed to access any android toolkits from any thread besides the UI thread, although I don't think I am doing that. If this is not the normal way to populate a SQLite android database, I of course am willing to learn where to do that as well.

although when I called my insert method from inside a new thread, they
do not seem to execute.
How can you say that? Are you seeing data entries in database? Or by looking only for restaurant ArrayList?
My doubt is you are not getting your Restaurant ArrayList because your Thread runs asynchronously.
And your next statement after Thread executed without waiting to fill restaurnat arrayList.
Solution:
Use AsyncTask call your database stuff in doInBackground() and get result in onPostExecute() and set adapter with result in the same method.

I suggest you to use AsyncTask.
Maybe something like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_bar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent intent = getIntent();
String barName = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
final TextView tv = (TextView) findViewById(R.id.name);
tv.setText(barName);
new AsyncTask<Void, Void, ArrayList<String>> {
protected Long doInBackground() {
DBHelper mydb = new DBHelper(ThisActivityClassName.this);
mydb.insertDrink("cake", "McD's", 8);
mydb.insertDrink("muffin", "The Woods", 8);
return mydb.getDrinks("The Woods");
}
protected void onPostExecute(ArrayList<String> restaurants) {
ArrayAdapter arrayAdapter=new ArrayAdapter(this,android.R.layout.simple_list_item_1, restaurants);
obj = (ListView)findViewById(R.id.listview);
obj.setAdapter(arrayAdapter);
}
}.execute();
}

Related

Error querying sqlite database in android studio

I have a problem in my application, to see if there is someone who can help me.
It turns out that in my application I have made a database with SQLite that has two tables, one for players and one for results.
#Override
public void onCreate(SQLiteDatabase BaseDeDades) {
BaseDeDades.execSQL("create table jugadors(codi int primary key, nom text, cognoms text, data date, club text, categoria text)");
BaseDeDades.execSQL("create table resultats(codipuntuacio int primary key, codijugador int,codiexercici text, puntuacio text, temps long, data date)");
}
To consult the first of the tables (players) that shows a list of all the players entered in the database, I did it as follows.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_llistajug);
Llistajugadors();
}
public void Llistajugadors(){
AdminSQLiteOpenHelper admin = new AdminSQLiteOpenHelper(this,"administracio",null,1);
SQLiteDatabase BaseDeDades = admin.getWritableDatabase();
if(BaseDeDades!=null){
Cursor c= BaseDeDades.rawQuery("select * from jugadors",null);
int quantitat = c.getCount();
int i=0;
String[] array = new String[quantitat];
if (c.moveToFirst()){
do{
String linia = c.getInt(0)+"-"+c.getString(1);
array[i] = linia;
i++;
}while(c.moveToNext());
}
ArrayAdapter<String>adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,array);
final ListView llista = (ListView)findViewById(R.id.llista);
llista.setAdapter(adapter);
llista.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = getIntent();
intent.putExtra("dato2", llista.getItemAtPosition(position).toString());
setResult(RESULT_OK,intent);
finish();
}
});
}
}
}
The problem has arisen when trying to consult the data of the other table (results) since I have tried to do it the same way
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_llistajug);
jugador = getIntent().getStringExtra("name");
exercici = getIntent().getStringExtra("exercise");
nom = jugador.split("-")[1];
codi = Integer.parseInt(jugador.split("-")[0]);
Resultats();
}
public void Resultats() {
AdminSQLiteOpenHelper admin = new AdminSQLiteOpenHelper(this, "administracio", null, 1);
SQLiteDatabase BaseDeDades = admin.getWritableDatabase();
if (BaseDeDades != null) {
Cursor c2 = BaseDeDades.rawQuery("select * from resultats",null);
int quantitat2 = c2.getCount();
int i2 = 0;
String[] array2 = new String[quantitat2];
if (c2.moveToFirst()) {
do {
String linia2 = c2.getInt(0) + "-" + c2.getString(1);
array2[i2] = linia2;
i2++;
} while (c2.moveToNext());
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, array2);
final ListView llista2 = (ListView) findViewById(R.id.llista2);
llista2.setAdapter(adapter);
}
}
}
But when executing this activity, in this case the application stops.
Does anyone know why if I have done it the same way? Thank you
This is the error that appears in Logcat when executing the activity:
Logcat error
Thanks, the bug was fixed. But now I have another problem with the query. How can I make the query for a string?
codijugador i codi are integers and it works correctly but adding another parameter codiexercici = exerici which are strings gives me an error, are they not done the same way?
Thanks, the bug was fixed. But now I have another problem with the query. How can I make the query for a string?
Thanks, the bug was fixed. But now I have another problem with the query. How can I make the query for a string?
co-player i codi are integers and it works correctly but adding another parameter codiexercici = exerici which are strings gives me an error, are they not done the same way?
Cursor c = BaseDeDades.rawQuery("select * from resultats where codijugador = "+codi+" and codiexercici="+exercici, null);
String must be enclosed inside single quotes, but this is something that you should not do by concatenating the parameters and the single quotes.
Use ? placeholders for the parameters and the 2nd argument of rawQuery() to pass them:
Cursor c = BaseDeDades.rawQuery(
"select * from resultats where codijugador = ? and codiexercici = ?",
new String[] {String.valueOf(codi), exercici}
);

How to call a non-static method from another activity's java class in Android?

So I have one java class called Details, which contains a non-static method called loadFavourites() and another java class called Favourites, which is implemented when the Favourites activity is started in my app.
I want to be able to call the method loadFavourites() from Details class in Favourites onCreate() method, however I am not sure how to do this...
I understand that I cannot create an instance of the Details class in order to access the method e.g.
Details details = new Details();
details.loadFavourites();
...as this does not work.
Also, I do not want my class or my method to be static as I have dynamic data involved.
Therefore, does anyone know a way in which I can call this non-static method from another class?
Here is a simplified version of my code...
In Details Activity:
FloatingActionButton addFav = (FloatingActionButton) findViewById(R.id.addFavBtn);
addFav.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
loadFavourites();
}});
public void loadFavourites() {
SQLiteDatabase db = dbHelper.getReadableDatabase();
String[] columns = {"favouriteId", "title", "owner", "url_m", "ownerPic", "description", "dateTaken"};
Cursor cursor = db.query("favourites", columns, null, null, null, null, "favouriteId");
Log.d("FavouritesDB", "" + cursor.getCount());
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
favID = cursor.getInt(0);
title = cursor.getString(1);
owner = cursor.getString(2);
url_m = cursor.getString(3);
ownerPic = cursor.getString(4);
description = cursor.getString(5);
date = cursor.getString(6);
// Add data to the array list for the recyclerview
ImageInfo favourite = new ImageInfo();
favourite.dateTaken = date;
favourite.description = description;
favourite.ownerPic = ownerPic;
favourite.url_m = url_m;
favourite.owner = owner;
favourite.title = title;
NetworkMgr.getInstance(this).favouritesImageList.add(favourite);
// Move to next entry
cursor.moveToNext();
}
cursor.close();
db.close();
}
In Favourites Activity:
public class Favourites extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.favourites_layout);
*this is where I want loadFavourites()*
}
}

Need Help Refreshing my database ListView in my app

My app layout apparently isn't a normal layout so I a having trouble setting my List Adapter to auto updated when an edit is made.
I make my edits to my database in this Java File which is controlled in its own activity and layout.
public void onClick(View view){
if (view == findViewById(R.id.addsave)) {
RecipeRepo repo = new RecipeRepo(this);
Recipe recipe = new Recipe();
if (editTextName.getText().toString().equals("")) {
editTextName.setError("Recipe name required!");
return;
} else {
recipe.name = editTextName.getText().toString();
}
if (textImagePath.getText().toString().equals("") ) {
recipe.image = ("");
}else{
recipe.image = textImagePath.getText().toString();
}
recipe.category = staticSpinner.getSelectedItem().toString();
if (editTextIngredients.getText().toString().equals("")) {
editTextIngredients.setError("Ingredient required!");
return;
} else {
recipe.ingredients = editTextIngredients.getText().toString();
}
if (editTextInstruct.getText().toString().equals("")) {
editTextIngredients.setError("Instruction required!");
return;
} else {
recipe.instructions = editTextInstruct.getText().toString();
}
recipe.cooktemp = editTextCookTemp.getText().toString();
recipe.cooktime = editTextCookTime.getText().toString();
recipe.serves = editTextServings.getText().toString();
recipe.recipe_Id = _Recipe_Id;
if (_Recipe_Id == 0) {
_Recipe_Id = repo.insert(recipe);
Toast.makeText(this, "New Recipe Added", Toast.LENGTH_SHORT).show();
finish();
it actually inserts and updates in this java file
int insert(Recipe recipe){
//Open connection to write data
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(Recipe.KEY_SERVES, recipe.serves);
values.put(Recipe.KEY_COOKTIME, recipe.cooktime);
values.put(Recipe.KEY_COOKTEMP, recipe.cooktemp);
values.put(Recipe.KEY_INSTRUCT, recipe.instructions);
values.put(Recipe.KEY_INGREDIENTS, recipe.ingredients);
values.put(Recipe.KEY_CATEGORY, recipe.category);
values.put(Recipe.KEY_IMAGE, recipe.image);
values.put(Recipe.KEY_NAME, recipe.name);
//Inserting Row
long recipe_Id = db.insert(Recipe.TABLE, null, values);
db.close();// Closing database connection
return (int) recipe_Id;
}
void delete(int recipe_Id){
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete(Recipe.TABLE, Recipe.KEY_ID + "=?", new String[] {String.valueOf(recipe_Id)});
db.close();
}
void update(Recipe recipe){
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(Recipe.KEY_SERVES, recipe.serves);
values.put(Recipe.KEY_COOKTIME, recipe.cooktime);
values.put(Recipe.KEY_COOKTEMP, recipe.cooktemp);
values.put(Recipe.KEY_INSTRUCT, recipe.instructions);
values.put(Recipe.KEY_INGREDIENTS, recipe.ingredients);
values.put(Recipe.KEY_CATEGORY, recipe.category);
values.put(Recipe.KEY_IMAGE, recipe.image);
values.put(Recipe.KEY_NAME, recipe.name);
db.update(Recipe.TABLE, values, Recipe.KEY_ID + "=?", new String[]{String.valueOf(recipe.recipe_Id)});
db.close();
}
and lastly it gets put into the list view from this Java file and separate layout. Which is where my adapters are but i cannot get the notifyDataSetChanged() to work here at all... as in it wont even come up.
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
RecipeRepo repo = new RecipeRepo(this);
if (id == R.id.nav_meat) {
final ArrayList<HashMap<String, String>> recipeList = repo.getRecipeMeat();
if(recipeList.size()!=0) {
ListView lv = (ListView) findViewById(R.id.list);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
recipe_Id = (TextView) view.findViewById(R.id.recipe_Id);
String recipeId = recipe_Id.getText().toString();
Intent objIndent = new Intent(getApplicationContext(), RecipeDetail.class);
objIndent.putExtra("recipe_Id", Integer.parseInt(recipeId));
startActivity(objIndent);
}
});
ListAdapter adapter = new SimpleAdapter(SousChef.this, recipeList, R.layout.view_recipe_entry, new String[]{"id", "category", "name"}, new int[]{R.id.recipe_Id, R.id.recipe_list_category, R.id.recipe_list_name});
lv.setAdapter(adapter);
}else {
Toast.makeText(this, "No recipe!", Toast.LENGTH_SHORT).show();
}
} else if (id == R.id.nav_veg) {
final ArrayList<HashMap<String, String>> recipeList = repo.getRecipeVeg();
if(recipeList.size()!=0) {
ListView lv = (ListView) findViewById(R.id.list);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
recipe_Id = (TextView) view.findViewById(R.id.recipe_Id);
String recipeId = recipe_Id.getText().toString();
Intent objIndent = new Intent(getApplicationContext(), RecipeDetail.class);
objIndent.putExtra("recipe_Id", Integer.parseInt(recipeId));
startActivity(objIndent);
}
});
ListAdapter adapter = new SimpleAdapter(SousChef.this, recipeList, R.layout.view_recipe_entry, new String[]{"id", "category", "name"}, new int[]{R.id.recipe_Id, R.id.recipe_list_category, R.id.recipe_list_name});
lv.setAdapter(adapter);
}else {
Toast.makeText(this, "No recipe!", Toast.LENGTH_SHORT).show();
}
So any advise on setting this up to automatically update would be a huge help. I have been racking my brain over this for a couple days now looking at different examples and what not, but no setup is quite like this one which doesnt allow me to have everything in one file.
And thank you in advance.
category picking image:
Category picking Image
There are for sure more answers but this is one that might help,
Quick Example for the proposed solution
SHORT EXPLANATION
inside MainActivity
//create a public static adapter
public static ListAdapter adapter
inside onCreateView()
//Create your adapter and set it to the right ListView
ListView lv = findViewById(R.id.listView_in_xml);
adapter = new SimpleAdapter(...)
lv.setAdapter(adapter)
inside CustomAdapter which in your case I assume is SimpleAdapter
//add a public method to be called so that the Adapter updates and displays the new data
public void updateMethod(){
//update your List<Recipe> that I would guess you have calling the database again
//if needed update your getCount() return value so that it returns the number of childs in your ListView which most of the cases is just the List<Recipe>.size()
//notifyDataSetChanged()
}
inside your DB HANDLER CLASS
//in every update, add, delete or any method that requires the ListView to Update just call the created method,
MainActivity.CustomAdapter.updateMethod();
PROBLEMS
You will have to make sure the public static adapter has been initialized and is not null, or simply check whether the adapter is not null and update, because if the adapter is null that activity has not launched yet thus no need to trigger the updateMethod().
OTHER SOLUTIONS
Instead of creating a public static adapter create a public static boolean, then whenever data changes set that boolean to true from the database.
Finally, whenever you resume your activity check against that boolean and update your ListViewAdapter if needed.
MORE COMPLICATED SOLUTIONS WHICH I KNOW WORK CAUSE I USE IT
Use TaskAsyncTaskLoader which utilizes a Loader in your MainActivity and implements LoaderManager.LoaderCallbacks.
Optionally, you can make the Loader be, public static Loaderand inside your DBHandler you trigger the loader to load the data again or use any other logic you want.
Proofs of Working suggested solution,
You can Broadcast Intent from the change database file after you get the response in the onCreate() of adapter loading class
Intent intent = new Intent("key_to_identify_the_broadcast");
Bundle bundle = new Bundle();
bundle.putString("edttext", "changed");
intent.putExtra("bundle_key_for_intent", bundle);
context.sendBroadcast(intent);
and then you can receive the bundle in your fragment by using the BroadcastReceiver class
private final BroadcastReceiver mHandleMessageReceiver = new
BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle =
intent.getExtras().getBundle("bundle_key_for_intent");
if(bundle!=null){
String edttext = bundle.getString("edttext");
}
//you can call any of your methods for using this bundle for your use case
}
};
in onCreate() of your adapter adding class you need to register the broadcast receiver first otherwise this broadcast receiver will not be triggered
IntentFilter filter = new IntentFilter("key_to_identify_the_broadcast");
getActivity().getApplicationContext().
registerReceiver(mHandleMessageReceiver, filter);
Finally you can unregister the receiver to avoid any exceptions
#Override
public void onDestroy() {
try {
getActivity().getApplicationContext().
unregisterReceiver(mHandleMessageReceiver);
} catch (Exception e) {
Log.e("UnRegister Error", "> " + e.getMessage());
}
super.onDestroy();
}

Android: Passing values to another activity's function and then to Sqlite database [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
It's been a month since I've kicked off with android studio, at this time I'm stuck at a point where I have to pass a set of <EditText/> values from MainActivity to UpdateActivity and then send those values to the Sqlite database for updating a table.
What I have accomplished:
Successfully sending values from MainActivity's <EditText/> to UpdateActivity's <EditText/>
How I have done that from MainActivity:
public class MainActivity extends AppCompatActivity {
DatabaseHelper myDb;
EditText editName, editSurname, editMarks;
Button btnUpdate;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myDb = new DatabaseHelper(this);
editName = (EditText) findViewById(R.id.UpdName);
editSurname = (EditText) findViewById(R.id.editTextSurname);
editMarks = (EditText) findViewById(R.id.UpdMarks);
btnUpdate = (Button)findViewById(R.id.btnUpdate);
btnUpdate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String MainName = editName.getText().toString();
String MainSurname = editSurname.getText().toString();
String MainMarks = editMarks.getText().toString();
Intent UpdateAct = new Intent(MainActivity.this, UpdateActivity.class);
UpdateAct.putExtra("Name", MainName);
UpdateAct.putExtra("SurName",MainSurname );
UpdateAct.putExtra("Marks", MainMarks);
startActivity(UpdateAct);
}
});
}
Then inside the UpdateActivity:
public class UpdateActivity extends AppCompatActivity {
DatabaseHelper myDb;
Button btnUpd;
EditText editTextId, editUpdtName, editUpdSurname, editUpdMarks;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_update);
Intent getData = getIntent();
String Name = getData.getStringExtra("Name");
String SurName = getData.getStringExtra("SurName");
String Marks = getData.getStringExtra("Marks");
editTextId = (EditText)findViewById(R.id.editTextID);
editUpdtName = (EditText)findViewById(R.id.UpdName);
editUpdSurname = (EditText)findViewById(R.id.UpdSurname);
editUpdMarks = (EditText)findViewById(R.id.UpdMarks);
btnUpd = (Button)findViewById(R.Id.btnUpd);
editUpdtName.setText(Name);
editUpdSurname.setText(SurName);
editUpdMarks.setText(Marks);
}
What I'm stuck at is to send these values to a function named updateData();
For that I have tried to use the values from MainActivity directly to UpdateActivity but failed, then I tried to cast those <EditText/> and use it inside the function but failed again.
Inside my UpdateActivity:
..//
editUpdtName.setText(Name);
editUpdSurname.setText(SurName);
editUpdMarks.setText(Marks);
//updateData(Name, SurName, Marks);
updateData();
}
//function definiton
// public void updateData(final String Name, final String SurName, final String Marks)
public void updateData()
{
btnUpd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// boolean isUpdated = myDb.updateData(editTextId.getText().toString(), Name,SurName, Marks);
boolean isUpdated = myDb.updateData(editTextId.getText().toString(), editUpdtName.getText().toString(),
editUpdSurname.getText().toString(), editUpdMarks.getText().toString());
if(isUpdated == true){
Toast.makeText(UpdateActivity.this, "Data Updated Successfully!", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(UpdateActivity.this, "Data NOT Updated!", Toast.LENGTH_SHORT).show();
}
}
});
}
}
The app crashes everytime the function updateData(); is called, to ensure that is the real cause I have even commented and also tried putting it in a handler to run it after 3000ms, as expcted it crashed after the time period.
Solved it by initializing the db.
myDb = new DatabaseHelper(this);
You forgot to initialize myDb.
Initialize it in your onCreate() method:
myDb = new DatabaseHelper(this);
Why not just pass the values to updateData()?
editUpdtName.setText(Name);
editUpdSurname.setText(SurName);
editUpdMarks.setText(Marks);
updateData(Name, SurName, Marks);
have you initialized btnUpd? I can not see this in your onCreate()
btnUpd = (Button) findViewById(...)

RecyclierView's notifyItemInserted does not work with arrayList

I have 1 ArrayList and 1 RecyclerView. Data from DB are retrieved and stored in the ArrayList for displaying in the RecyclerView. All the things work fine with adding new item to the RecyclerView, but without the adding animation. I know I should use notifyItemInserted for the adding animation, but it didn't work. No inserting animation was appearing. Now I have to go back to the previous page and then get in the page again so that the added item was showing. So, how to add back the inserting animation?
Any help will be very much appreciated. Thanks.
Code to pass the data and set the adapter:
db = new DatabaseHelper(this);
dbList = new ArrayList<>();
dbList = db.getFilteredItems();
RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(this);
llm.setOrientation(LinearLayoutManager.VERTICAL);
//newest to oldest order (database stores from oldest to newest)
llm.setReverseLayout(true);
llm.setStackFromEnd(true);
mRecyclerView.setLayoutManager(llm);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
adapter = new RecyclerAdapter(this, llm, dbList);
mRecyclerView.setAdapter(adapter);
Code to retrieve data from DB:
//retrieve filtered data from DB
public List<AudioItem> getFilteredItems(){
List<AudioItem> audioList = new ArrayList<>();
String titleName = EditActivity.titleName;
String query = "select * from " + TABLE_NAME + " where " + COLUMN_NAME_RECORDING_NAME + " like '" + titleName + "%'";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query,null);
if (cursor.moveToFirst()){
do {
AudioItem audio = new AudioItem();
audio.setId(Integer.parseInt(cursor.getString(0)));
audio.setName(cursor.getString(1));
audio.setFilePath(cursor.getString(2));
audio.setLength(Integer.parseInt(cursor.getString(3)));
audio.setTime(Long.parseLong(cursor.getString(4)));
audioList.add(audio);
}while (cursor.moveToNext());
cursor.close();
}
return audioList;
}
Code to insert data into the DB:
/* Insert data into database */
public void addRecording(String recordingName, String filePath, long length) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(COLUMN_NAME_RECORDING_NAME, recordingName);
cv.put(COLUMN_NAME_RECORDING_FILE_PATH, filePath);
cv.put(COLUMN_NAME_RECORDING_LENGTH, length);
cv.put(COLUMN_NAME_TIME_ADDED, System.currentTimeMillis());
db.insert(TABLE_NAME, null, cv);
db.close();
if (mOnDatabaseChangedListener != null) {
mOnDatabaseChangedListener.onNewDatabaseEntryAdded();
}
}
Code to invoke the inserting animation:
#Override
public void onNewDatabaseEntryAdded() {
//item added to top of the list
Log.e("Count: ", Integer.toString(getItemCount()));
// notifyDataSetChanged();
notifyItemInserted(getItemCount());
//llm.scrollToPosition(getItemCount() - 1);
}
If you make a new ArrayList every time something changes and assign it to a new adapter and assign that new adapter to the RecyclerView, wonky things happen.
You should break the ArrayLists out into a Model type of object or integrate them into your current DB model object. If you do this, you can simply update itemlist and the changes will be reflected in your RecyclerView.
Here's some pseudo code since I don't really have much of your code to work off of:
public class DataModel {
private ArrayList<Foo> itemlist = new ArrayList<>();
public DataModel(){}
public ArrayList<Foo> getItemList() { return itemlist; }
}
public class YourActivity extends Activity {
private DataModel data = new DataModel();
#Override
protected void onCreate(Bundle b) {
if (b == null) {
RecyclerView dataView = (RecyclerView) findViewById(R.id.recyclerView);
dataView.setAdapter(new RecyclerAdapter(this, new LinearLayoutManager(this), data.getItemList()));
}
}
}
After you set things up this way, whenever you update itemlist, you should be seeing the changes automatically reflected. If not, call notifyDataSetChanged().

Categories