I am currently unable to view newly inserted sqlite data from my ListView without restarting my whole application. Currently when a ListView item is selected, a new activity starts showing detailed information. once the detailed info is updated, edited, or the item is deleted the ListView is shown again but contain all original data unless app it closed and restarted. list view OnResume method is below. How do I refresh ListView when ever it is shown on screen. my attempts on adding .notifyDataSetChanged was unsuccessful. Not sure I implemented it correctly.
public List<String> populateList (){
List<String> webNameList = new ArrayList<String>();
dataStore openHelperClass = new dataStore (this);
SQLiteDatabase sqliteDatabase = openHelperClass.getReadableDatabase();
Cursor cursor = sqliteDatabase.query(dataStore.TABLE_NAME_INFOTABLE, null, null, null, null, null, dataStore.COLUMN_NAME_SITE, null);
startManagingCursor(cursor);
while (cursor.moveToNext()){
String sName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_SITE));
String wUrl = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_ADDRESS));
String uName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_USERNAME));
String pWord = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_PASSWORD));
String lNotes = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_NOTES));
LoginDetails lpDetails = new LoginDetails();
lpDetails.setsName(sName);
lpDetails.setwUrl(wUrl);
lpDetails.setuName(uName);
lpDetails.setpWord(pWord);
lpDetails.setlNotes(lNotes);
loginArrayList.add(lpDetails);
webNameList.add(sName);
}
sqliteDatabase.close();
return webNameList;
}
#Override
protected void onResume() {
super.onResume();
loginListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, populateList());
loginList.setAdapter(loginListAdapter);
}
#Override
public void onItemClick(AdapterView<?> arg0 , View arg1, int arg2, long arg3) {
Toast.makeText(getApplicationContext(), "Selected ID :" + arg2, Toast.LENGTH_SHORT).show();
Intent updateDeleteLoginInfo = new Intent (this, UpdateDeleteLoginList.class);
LoginDetails clickedObject = loginArrayList.get(arg2);
Bundle loginBundle = new Bundle();
loginBundle.putString("clickedWebSite",clickedObject.getsName());
loginBundle.putString("clickedWebAddress",clickedObject.getwUrl());
loginBundle.putString("clickedUserName",clickedObject.getuName());
loginBundle.putString("clickedPassWord",clickedObject.getpWord());
loginBundle.putString("clickedNotes",clickedObject.getlNotes());
updateDeleteLoginInfo.putExtras(loginBundle);
startActivity(updateDeleteLoginInfo);
You're using startActivity. Why don't you use startActivityForResult instead? The answer to this question details how you would call the second Activity. Once it returns, you would have to use the notifyDataSetChanged() call.
startManagingCursor is deprecated.
Use CursorLoader instead.
It's very simple to use and updates your data in the ListView immediately when the data of the ContentProvider changes.
Here is a nice example:
http://www.vogella.com/articles/AndroidSQLite/article.html#todo_activities
You are only showing part of the app code, so I may be offbase here, but it appears you are using a Cursor to return a List and use the List to create an ArrayAdapter...
If you want the data to be 'fresh', why not use a CursorLoader with the LoaderManager? There are several benefits to the LoaderManager (like moving the query off of the UI thread), and the LoaderManager does a bit of the heavy lifting for you when it comes to monitoring the DB for changes.
There is a blog post that I've found quite helpful - http://www.androiddesignpatterns.com/2012/07/understanding-loadermanager.html
Related
I'm pretty new to an Android development and currently trying to write an app that will show tomorrow's weather of multiple cities. Sorry for any incorrent termins that I might use in this question.
What I want to reach:
App will fetch data from local database, then build a HTTP query on the data fetched from a DB, get JSON response and form a list elements.
What I currently have:
Everything except SQL functionality.
Here is the snapshot of my main activity code. I use LoaderCallbacks<List<Weather>> to build URI with needed parameters in onCreateLoader(int i, Bundle bundle), send HTTP query and get the data via WeatherLoader(this, uriList), and form elements results in a List using WeatherAdapter.
public class WeatherActivity extends AppCompatActivity
implements LoaderCallbacks<List<Weather>>,
SharedPreferences.OnSharedPreferenceChangeListener {
private static final int WEATHER_LOADER_ID = 1;
private WeatherAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.weather_activity);
ListView weatherListView = (ListView) findViewById(R.id.list);
mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
weatherListView.setEmptyView(mEmptyStateTextView);
mAdapter = new WeatherAdapter(this, new ArrayList<Weather>());
weatherListView.setAdapter(mAdapter);
...
weatherListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
Weather currentWeather = mAdapter.getItem(position);
Uri forecastUri = Uri.parse(currentWeather.getUrl());
Intent websiteIntent = new Intent(Intent.ACTION_VIEW, forecastUri);
startActivity(websiteIntent);
}
});
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
LoaderManager loaderManager = getLoaderManager();
loaderManager.initLoader(WEATHER_LOADER_ID, null, this);
} else {
View loadingIndicator = findViewById(R.id.loading_indicator);
loadingIndicator.setVisibility(View.GONE);
mEmptyStateTextView.setText(R.string.no_internet_connection);
}
}
#Override
public Loader<List<Weather>> onCreateLoader(int i, Bundle bundle) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
String tempUnit = sharedPrefs.getString(
getString(R.string.settings_temp_unit_key),
getString(R.string.settings_temp_unit_default));
List<String> uriList = new ArrayList<>();
/***
*
* Here we input cities for which we want to see the forecast
*
* ***/
List<String> cities = new ArrayList<>();
cities.add("London,uk");
cities.add("Kiev,ua");
cities.add("Berlin,de");
cities.add("Dubai,ae");
//For each city in the list generate URI and put it in the URIs list
for (String city : cities){
Uri baseUri = Uri.parse(OWM_REQUEST_URL);
Uri.Builder uriBuilder = baseUri.buildUpon();
uriBuilder.appendQueryParameter("q", city);
uriBuilder.appendQueryParameter("cnt", "16");
uriBuilder.appendQueryParameter("units", tempUnit);
uriBuilder.appendQueryParameter("appid", "some_key");
uriList.add(uriBuilder.toString());
}
return new WeatherLoader(this, uriList);
}
#Override
public void onLoadFinished(Loader<List<Weather>> loader, List<Weather> weatherList) {
mAdapter.clear();
// If there is a valid list of forecasts, then add them to the adapter's
// data set. This will trigger the ListView to update.
if (weatherList != null && !weatherList.isEmpty()) {
mAdapter.addAll(weatherList);
}
}
#Override
public void onLoaderReset(Loader<List<Weather>> loader) {
mAdapter.clear();
}
As you see, cities are "hardcoded" via List<String> cities = new ArrayList<>(); in onCreateLoader(int i, Bundle bundle). That's why I've decided to implement SQL storage of cities in my app. I know how to implement SQL functionality in android app using ContentProvider and CursorAdapter.
So what's the problem?
If I am correct we should use LoaderManager.LoaderCallbacks<Cursor> if we want to make a query to a local DB.
Unfortunately, I can't imagine how to merge current LoaderCallbacks<List<Weather>> and LoaderCallbacks<Cursor> in one activity to make it work as I want.
Actually, I want to change
List<String> cities = new ArrayList<>();
on something like
Cursor cursor = new CursorLoader(this, WeatherEntry.CONTENT_URI, projection, null, null, null); to build the URI on the results that CursorLoader returns.
But, we should make SQL query in separate thread and HTTP query also(!) in separate thread. Should we do nested threads/loaders (http query in a scope of sql fetching data and return a List<T>)? Even can't imagine how it's possible to do, if so...
Help me please, I've stuck!
Ok, it was not obvious to me at the first sight, but I finally solved the problem.
In the question above we had a list of cities that were hardcoded:
List<String> cities = new ArrayList<>();
cities.add("London,uk");
cities.add("Kiev,ua");
cities.add("Berlin,de");
cities.add("Dubai,ae");
Even if we assume that we will change it to a DB query, like this:
// Connect to a DB
...
Cursor forecastCitiesDataCursor = mDb.query(true, WeatherContract.WeatherEntry.TABLE_NAME, projection,
null, null, null,
null, null, null);
...
// Fetch data from cursor
...we will have that SQL query on the main thread. So we need a solution.
The best thing that I've found for me, it is put that SQL query in CustomLoader class and pass needed parameters in a constructor (in my case, it is SharedPreferences parameter to built an HTTP query).
Here is my code:
WeatherActivity.java
public class WeatherActivity extends AppCompatActivity implements LoaderCallbacks<List<Weather>>,
SharedPreferences.OnSharedPreferenceChangeListener {
...
#Override
public Loader<List<Weather>> onCreateLoader(int i, Bundle bundle) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
String tempUnit = sharedPrefs.getString(
getString(R.string.settings_temp_unit_key),
getString(R.string.settings_temp_unit_default));
return new WeatherLoader(this, tempUnit);
}
#Override
public void onLoadFinished(Loader<List<Weather>> loader, List<Weather> weatherList) {
// Hide loading indicator because the data has been loaded
View loadingIndicator = findViewById(R.id.loading_indicator);
loadingIndicator.setVisibility(View.GONE);
// Set empty state text to display "No forecasts found."
mEmptyStateTextView.setText(R.string.no_forecasts);
// Clear the adapter of previous forecasts data
mAdapter.clear();
// If there is a valid list of forecasts, then add them to the adapter's
// data set. This will trigger the ListView to update.
if (weatherList != null && !weatherList.isEmpty()) {
mAdapter.addAll(weatherList);
}
}
WeatherLoader.java
public class WeatherLoader extends AsyncTaskLoader<List<Weather>> {
...
// Pass parameters here from WeatherActivity
public WeatherLoader(Context context, String tmpUnit) {
super(context);
mTempUnit = tmpUnit;
}
#Override
protected void onStartLoading() {
forceLoad();
}
/**
* This is on a background thread.
*/
#Override
public List<Weather> loadInBackground() {
// List for storing built URIs
List<String> uriList = new ArrayList<>();
// List for storing forecast cities
List<String> cities = new ArrayList<>();
// Define a projection that specifies the columns from the table we care about.
...
Cursor forecastCitiesDataCursor = mDb.query(true, WeatherContract.WeatherEntry.TABLE_NAME, projection,
null, null, null,
null, null, null);
// Get list of cities from cursor
...
//For each city in the list generate URI and put it in the URIs list
for (String city : cities){
Uri baseUri = Uri.parse(OWM_REQUEST_URL);
Uri.Builder uriBuilder = baseUri.buildUpon();
uriBuilder.appendQueryParameter("q", city);
uriBuilder.appendQueryParameter("cnt", "16");
uriBuilder.appendQueryParameter("units", mTempUnit);
uriBuilder.appendQueryParameter("appid", /*some id*/);
uriList.add(uriBuilder.toString());
}
if (uriList == null) {
return null;
}
// Perform the network request, parse the response, and extract a list of forecasts.
List<Weather> forecasts = QueryUtils.fetchForecastData(uriList);
return forecasts;
}
So what we've got?
We've implemented persistent data storage within the work with ArrayAdapter that are used to do an HTTP query then. SQL query are on the separate thread and we'll have no problem with app performance.
Hope that solution will help somebody, have a nice day!
It shows database first data, but i want to show all data which number is 3 column table of each row, and after it will open after click a button and open this list in a new activity
//Read Database
public void readDB(View v) {
SQLiteDatabase db2 = openOrCreateDatabase(" Result ", MODE_PRIVATE, null);
String strThree = "SELECT * FROM my_result";
Cursor c = db2.rawQuery(strThree, null);
c.moveToNext();
String grade = c.getString(c.getColumnIndex("Grade_Point"));
String ss = c.getString(c.getColumnIndex("Subject_Name"));
Toast.makeText(getApplicationContext(), " Subject Name is "+ss+" and Gragde point is"+grade , Toast.LENGTH_LONG).show();
}
Store the extracted values from your column 3 into a variable preferably in an arraylist. Then On the click of your button send it to your activity and populate your listview in that activity in the onCreate() method of that activity. Example below(Not tested)
ArrayList<String> col_3 = new ArrayList<String>();
void readDB(View v){
SQLiteDatabase db2 = openOrCreateDatabase(" Result ", MODE_PRIVATE, null);
String strThree = "SELECT * FROM my_result";
Cursor c = db2.rawQuery(strThree, null);
while(c.moveToNext()!=null){
col_3.add(c.getString(2)) //since 3rd column
}
}
Now on the onClick of your button send it to the destination activity via intents
Intent intent = new Intent(CurrentActivity.this, DestinationActivity.class);
intent.putStringArrayListExtra("col_3_data", col_3);
startActivity(intent);
onCreate() method of your destination Activity will be something like this
Intent i = new Intent();
ArrayList col_value =new ArrayList<String>();
col_value = i.getStringArrayListExtra("col_3_data");
ListView lv = (ListView)findViewById(R.id.my_lsitview); //my_listview is your listview where you want to display your data
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, col_value );
lv.setAdapter(arrayAdapter);
I suggest instead of creating a new activity, you can create a dialog with listview, follow one of the following tutorials:
http://envyandroid.com/creating-listdialog-with-images-and-text/
http://www.edumobile.org/android/custom-listview-in-a-dialog-in-android/
I have a sqlite database prepopulated with some data and I would like to have method/function that enables the user to "save" the info in his favorites and display it. The only problem is i have problems with the queries to work properly. I don't understand how to get the position from the current displayed data (from the db) in the activity and save it to the database. I have a column called "Favorites" in db with the default value set to "no" and when the user click a button the value should change to "yes".
The user click a row in listview populated from the DB and it starts a new activity with intent.putExtra(data from db). The new activity displays the data in a single textview. In this new activity i've made a navigation drawer/listview(shows by sliding or "hamburger meny"). In this nav drawer I have a "button" that i would like to get the id from the db according to the current displayed data and change the value of the column "Favorite". In a another class i used
Cursor c = dbHelper.showBook(Integer.toString(position + 1));
Got this help from another recent thread of mine and it worked fine but my new problem is that i have if statements as below. The start of intent works fine. But I want to call a method from my dbHelper to update rows in db. And the code above dont work(but no errors) when i try to use it. The toast shows but nothing is happening in the DB.
myDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (position == 0){
Intent iHome = new Intent(DisplayBook.this, MyAccont.class);
startActivity(iHome);
else if (position == 3){
dbHelper.addFavorites(Integer.toString(position+ 1));
Toast.makeText(getApplicationContext(), "Added to favorites", Toast.LENGTH_SHORT).show();
the dbHelper.addFavorites: (the addFavs param is supposed to be the id/pos of the db row as in the working code above)
public void addFavorites(String addFavs){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COL_FAV, "yes");
String whereClause = COL_ID + " = ?" ;
String[] whereArgs = new String[] { addFavs};
db.update(
TABLE_NAME,
values,
whereClause,
whereArgs);
}
I've tried a fair amount of versions och different codes and stuff but nothing works and now I'm asking for som advice on this. How can i do it in a good an efficient way? Thank you so much for any help at all!
EDIT: Solved it by using arrays instead of stringbuilder. I save the id from the database in [0] and used it in dbHelper.addFavorites(myStringArray[0]);
and in
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Cursor c = dbHelper.aClass(Integer.toString(position + 1));
StringBuilder sb = new StringBuilder();
while (c.moveToNext()) {
myStringArray[0] = c.getString(0);
myStringArray[1] = c.getString(4);
Intent i = new Intent(classA.this, classB.class);
i.putExtra(null, myStringArray);
startActivity(i);
I'm not shure, but your problem may be this line
ContentValues values = new ContentValues();
try to change it to:
ContentValues values = new ContentValues(1);
From my experience u should write amount of variables u want to send to your db.
i have a listview with data from database using an sqlite.
when first time (onCreate()) i show the data, there`s no problems, the data all shown.
the problem is, when i want to filter my list view using datepicker and button, the listview not change the data.
ive use listview.invalidateViews(), notifyDataSetChanged()... but still not solved yet. maybe theres some mistake with my code... hope you guys can give me some solution.
thx...
here`s my code
Getting Data From DataBase
public ArrayList<BonRokokModel> getBonRokokList(String userGUID, String transDate, String searchText){
dbPath = "/data/data/app.chameleon.mobile/databases/";
dbName = "SalesTrans.sqlite";
bonRokok = SQLiteDatabase.openDatabase(dbPath + dbName, null,SQLiteDatabase.OPEN_READWRITE);
String strQuery;
strQuery = "SELECT BonRokokID, TransDate, Gudang, Status FROM tblSATBonRokok WHERE UserGUID = ? AND TransDate = ?";
// if(!searchText.equals("")){
// strQuery += "AND (BonRokokID LIKE %'"+ searchText +"'% ) ORDER BY TransDate DESC, BonRokokID Desc";
// }
ArrayList<BonRokokModel> listRokok = new ArrayList<BonRokokModel>();
Cursor mCursor = bonRokok.rawQuery(strQuery, new String[]{userGUID, transDate});
if(mCursor.moveToFirst()){
do {
BonRokokModel dataRokok = new BonRokokModel();
dataRokok.setBonRokokID(mCursor.getString(mCursor.getColumnIndex("BonRokokID")));
dataRokok.setTransDate(mCursor.getString(mCursor.getColumnIndex("TransDate")));
dataRokok.setGudang(mCursor.getString(mCursor.getColumnIndex("Gudang")));
dataRokok.setStatus(mCursor.getString(mCursor.getColumnIndex("Status")));
listRokok.add(dataRokok);
} while (mCursor.moveToNext());
}
bonRokok.close();
return listRokok;
}
My Code to Get Data
public void settingTabItem() {
listView = (ListView) findViewById(R.id.bonRokokMain_lvMain);
listviewMain = new ArrayList<BonRokokModel>();
listviewMain = bonRokokDAO.getBonRokokList(Main_Login.userGUID,utilities.convertDateToDateDBString(edt1.getText().toString()),"");
BonRokokListAdapter adapter = new BonRokokListAdapter(this, listviewMain);
listView.setAdapter(adapter);
}
thank you
Try like this ..
ListArrayAdapter.clear(); // Clear your adapter
ListArrayAdapter.addAll(newItems); // Add new items to it
ListArrayAdapter.notifyDataSetChanged(); // Notify List view for new items in list
OR
You can update list view like this also ..
Firstly clear your list view ..
Then after fetching new data .... create complete list view again.
Use the logical of method settingTabItem() on refresh method. Don't forget to clear the listview. Sorry for the bad English.
I need to create a drop down list (spinner) in eclipse for Android whereby the drop down options can be created by the user.
To do this I've created a SQLiteDatabase, which I want to convert into a string array to be put into an array adapter, which can then be fed into the spinner.
Database details are:
DATABASE_NAME = "carddb"
DATABASE_TABLE = "cardtable"
Then the column I wish to read the values from is:
KEY_CARDDETAILS = "_carddetails";
Here is my code so far, adapted from another question on this site (Link: how to get the database value to a String array in android(sqlite Database))
myDB = cardtable.this.openOrCreateDatabase("carddb", MODE_PRIVATE, null);
Cursor cardcursor = cardDB.rawQuery("SELECT * FROM cardtable");
String[] cardstringarray = new String[cardcursor.getCount()];
cardcursor.moveToFirst();
int counter = 0;
while(cardcursor.moveToNext()){
String carddetailss = cardcursor.getString(cardcursor.getColumnIndex("NAME"));
cardstringarray[counter] = carddetailss;
counter++;
}
I'm getting an error under "myDB" and "cardtable", both errors saying they cannot be resolved into a variable!
PLEASE HELP!
Use this code
String[] displayName={};
ArrayList<String> List=new ArrayList<String>();
myDB = cardtable.this.openOrCreateDatabase("carddb", MODE_PRIVATE, null); Cursor cardcursor = cardDB.rawQuery("SELECT * FROM cardtable");
String[] cardstringarray = new String[cardcursor.getCount()];
cardcursor.moveToFirst();
int counter = 0;
while(cardcursor.moveToNext()){
String carddetailss = cardcursor.getString(cardcursor.getColumnIndex("NAME"));
List.add(carddetailss);
counter++;
}
if(List != null){
listEmail=(ListView)findViewById(R.id.listEmail);
listEmail.setVisibility(view.VISIBLE);
displayName=(String[])List.toArray(new String[0]);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, displayName);
// Assign adapter to ListView
listEmail.setAdapter(adapter);
}
This is work for you. Use spinner instead of listView.