loaderManager recyclerview imageview viewholder content provider fails - cursor

I am new at android and new at posting here and trying a sink in slowly but am stuck here at inflating imageViews. Below am providing code snippets from my app that i would thank you for your help
Here is my table
private static final String CREATE_TABLE = "CREATE TABLE "+TABLE_NAME+" ("+KEY_ID,"+KEY_PROFILEPIC+" BLOB,"+KEY_IMAGE+" BLOB)";
this is my viewholder class
`public CityHolder(final View view) {
super(view);
ButterKnife.bind(this, itemView); }
public void bindData(final Cursor cursor) {
String name = cursor.getString(cursor.getColumnIndex("name"));
this.name.setText(name);
String CircularNetWorkImageView =cursor.getString(cursor.getColumnIndex("profilePic"));
this.CircularNetWorkImageView.setText(CircularNetWorkImageView);
}
`
and then i am using recyclerview to bind to cursor.
am also using a a content Provider to both insert and then retrieve data and load by use of the LoaderManager.LoaderCallbacks
here is how i get the data through volley json
JSONArray jsonArray = response.getJSONArray("city");
for (int i=0;i<jsonArray.length();i++)
{
JSONObject jsonObjectCity = jsonArray.getJSONObject(i);
String name = jsonObjectCity.getString("name");
String profilePic = jsonObjectCity.getString("profilePic");
String image = jsonObjectCity.getString("image");
City city = new City();
city.setName(name);
city.setProfilePic(profilePic);
city.setImage(image);
ContentValues values = new ContentValues();
values.put(CityDb.KEY_NAME, name);
values.put(CityDb.KEY_PROFILEPIC, profilePic);
values.put(CityDb.KEY_IMAGE, image);
getContentResolver().insert(CityContentProvider.CONTENT_URI, values);
}
}catch(JSONException e){e.printStackTrace();}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Volley","Error");
}
}
);
requestQueue.add(jor);
}
#Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
String[] allColumns = new String[] {
CityDb.KEY_ID,
CityDb.KEY_NAME,
CityDb.KEY_PROFILEPIC,
CityDb.KEY_IMAGE
};
return new CursorLoader(this,CityContentProvider.CONTENT_URI,allColumns, null, null, null);
}`
Now the String Name is displayed in my fragment but am having issue getting the image and profilePic in circularNetworkimageView to display.
what could i be missing, please guide me

Related

Query in Firebase database child

I'm new to android. Can someone help me to query the below-underlined line in the firebase? The query result should be the underlined String.
That String is an autogenerated one in the firebase at the Driver signup. So hardcoding that string is not my aim.
Refer to Users/Driver and loop through children, you will get your key:
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference().child("Users").child("Driver");
ValueEventListener listener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//loop through the children
for(DataSnapshot ds: dataSnapshot.getChildren()){
//get the key or keys depending on how many keys
String underLinedKey = ds.getKey();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
//log error
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
}
};
mDatabase.addValueEventListener(listener);

Exception when trying to use DynamoDBMapper: no mapping for HASH key

I have a DynamoDB table with a primary key (id : integer) and secondary key (dateTo : String). I've made a Class that utilizes DynamoDBMapper:
#DynamoDBTable(tableName="MyItems"
public class MyItemsMapper {
private int id;
private String dateTo;
private String name;
#DynamoDBHashKey(attributeName="id")
public void setId(int id) { this.id = id; }
public int getId() { return id; }
#DynamoDBAttribute(attributeName="dateTo")
public void setDateTo(String dateTo) { this.dateTo = dateTo; }
public String getDateTo() { return dateTo; }
#DynamoDBAttribute(attributeName="name")
public void setName(String name { this.name = name; }
public String getName() { return name; }
public boolean saveItem(MyItemsMapper item) {
try {
DynamoDBMapper mapper = new DynamoDBMapper(client); //<-- This connects to the DB. This works fine.
item.setId(generateUniqueNumber()); //<-- This generates a unique integer. Also seems to work fine.
mapper.save(item);
logger.info("Successfully saved item. See info below.");
logger.info(item.toString());
return true;
} catch (Exception e) {
logger.error("Exception while trying to save item: " + e.getMessage());
e.printStackTrace();
return false;
}
}
}
I then have a manager class that uses the bean above, like so:
public class MyManager {
public boolean recordItem(
int id,
String dateTo,
String name,
) {
MyItemsMapper myItemsMapper = new MyItemsMapper();
myItemsMapper.setId(id);
myItemsMapper.setDateTo(dateTo);
myItemsMapper.setName(name);
myItemsMapper.saveItem(myItemsMapper);
}
}
I am running the manager class in a JUnit test:
public class MyManagerTest {
#Test
public void saveNewItemTest() {
MyManager myManager = new MyManager();
myManager.recordItem(1234567, "2018-01-01", "Anthony");
}
}
When I use the saveItem method above via my manager by running my JUnit test, I get the following error:
com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException: MyItemsMapper; no mapping for HASH key
Not really sure what it's pertaining to, as I definitely have a primary key for my table and my secondary key always has a value as well.
How do I get this to work?
More Info:
It's worth noting that I can record data into my DynamoDB table via the Item object. If I do the below, my data gets recorded into the database:
DynamoDB dynamoDB = new DynamoDBClient().connectToDynamoDB(); //<--
Connection. Works fine.
Table table = dynamoDB.getTable("MyItems");
item.withPrimaryKey("id", 1234567);
item.withString("dateTo", "2018-01-01");
item.withString("name", "Anthony");
PutItemOutcome outcome = table.putItem(item);
However, I'm trying to use DynamoDBMapper because I'm reading that it is a more organized, better way to access data.
Im not sure if this is causing the problem, but you are creating the myItemsMapper object, then passing a reference to this object to itself.
I would suggest removing your saveItem method. The MyItemsMapper class should be a plain old java object. Then make MyManager like this
public class MyManager {
public boolean recordItem(
int id,
String dateTo,
String name,
) {
MyItemsMapper myItemsMapper = new MyItemsMapper();
myItemsMapper.setId(id);
myItemsMapper.setDateTo(dateTo);
myItemsMapper.setName(name);
DynamoDBMapper mapper = new DynamoDBMapper(client);
mapper.save(myItemsMapper);
}
}
If you particularly want to keep the saveItem method make it like this
public boolean saveItem() {
try {
DynamoDBMapper mapper = new DynamoDBMapper(client);
mapper.save(this);
logger.info("Successfully saved item. See info below.");
logger.info(this.toString());
return true;
} catch (Exception e) {
logger.error("Exception while trying to save item: " + e.getMessage());
e.printStackTrace();
return false;
}
}
And then in MyManager do
MyItemsMapper myItemsMapper = new MyItemsMapper();
myItemsMapper.setId(id);
myItemsMapper.setDateTo(dateTo);
myItemsMapper.setName(name);
myItemsMapper.saveItem();

Store JSON Array from NewsAPI in Firebase

I have used volley to parse news data from the newsAPI.org. I want to save the response to Firebase for offline viewing and persistence.
This is the sample response from API:
articles: [
{
author: "Megan Rose Dickey",
title: "Ojo wants to be the electric scooter for commuters, but...",
description: "Commuting in a busy city like San Francisco can be
annoying..",
url: "https://techcrunch.com/2017/08/23/ojo-wants-to-be-the-electric-
scooter-for-commuters-but-its-not-there-yet/",
urlToImage: "https://img.vidible.tv/prod/2017",
publishedAt: "2017-08-23T21:19:56Z"
},
{
author: "Katie Roof",
title: "Pishevar intervenes in Benchmark-Kalanick lawsuit",
description: "Early Uber investor and former board member Shervin
Pishevar is speaking out against Benchmark again..",
url: "https://techcrunch.com/2017/08/24/pishevar-sends-another-letter-
to-uber-board-about-benchmark/",
urlToImage:"https://tctechcrunch2011.files.wordpress.com/",
publishedAt: "2017-08-24T22:49:59Z"
},
In total I have 5 objects inside the articles array.
I want to store each of the objects in Firebase database. This is what I have tried:
StringRequest stringRequest = new StringRequest(Request.Method.GET, Constants.NEWS_ENDPOINT,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if (response != null){
Log.d(TAG, "News Api Response is: \t" + response.toString());
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray articles = jsonObject.getJSONArray("articles");
for (int i = 0; i < articles.length(); i++){
JSONObject items = articles.getJSONObject(i);
final String title_news = items.getString("title");
final String desc_news = items.getString("description");
final String urlImg = items.getString("urlToImage");
final String author_news = items.getString("author");
final String url = items.getString("url");
final String publishedAt = items.getString("publishedAt");
NewsItem newsItem = new NewsItem(author_news, title_news, desc_news, url, urlImg, publishedAt);
itemList.add(newsItem);
/**
* Save JSON Results to Firebase
* */
for (int k = 0; k < articles.length(); k++){
HashMap hashMap = new HashMap();
hashMap.put("newsTitle", title_news);
hashMap.put("newsDesc", desc_news);
hashMap.put("newsImageUrl", urlImg);
hashMap.put("newsAuthor", author_news);
hashMap.put("newsUrl", url);
hashMap.put("newsDate", publishedAt);
newsRootRef.setValue(hashMap);
}
When I check the console, it saves only one object, the last object like this:
I want to store all objects AS-IS in the response array and retrieve them later. Is there another way to do this? Thanks, sorry for the long post.
In this case you need to use push() to store the data. Otherwise you are just replacing the data at the reference at each iteration. This is why it seems that only the last record gets stored. Try to change this line:
newsRootRef.setValue(hashMap);
...into this:
newsRootRef.push().setValue(hashMap);
To avoid duplicating entries I recommend that you fetch all entries from Firebase and cache the url property (since this property seems to be unique) in a HashSet. Then you can modify your code like this:
if (!urlSet.contains(url)) {
HashMap hashMap = new HashMap();
hashMap.put("newsTitle", title_news);
hashMap.put("newsDesc", desc_news);
hashMap.put("newsImageUrl", urlImg);
hashMap.put("newsAuthor", author_news);
hashMap.put("newsUrl", url);
hashMap.put("newsDate", publishedAt);
newsRootRef.push(),setValue(hashMap);
}
But of course you need to populate your HashSet first so I'd recommend doing something like this:
final Set<String> urlSet = new HashSet<>();
newsRootRef.addChildEventListener(new ChildEventListener() {
int i = 0;
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
urlSet.add(dataSnapshot.getValue(String.class));
if (i++ == dataSnapshot.getChildrenCount()) {
...
...your code...
StringRequest stringRequest = new StringRequest(Request.Method.GET, Constants.NEWS_ENDPOINT,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
...
...
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

Create string array from SQLite database column in Android Studio

I have created an app with an SQLite database and a ListView that I want to populate using the database. To do this I have written an adapter class called HomeListAdapter. This class takes 4 string arrays as input and that is where my problem is. At first, I just used random string arrays to populate the ListView by typing them myself, for example:
String[] homelist_name_short = {
"Flower", "Bush", "Tree"};
String[] homelist_name_long = {
"Red rose", "Berry bush", "Oak"};
String[] homelist_date = {
"20-9-2017", "11-10-2017", "12-10-2017"};
String[] homelist_price = {
"€1.50", "€2.48", "€0.68"};
Now I want this to be put into the listview automatically and to do that I have written the code that can be seen below..
I have created a class called Home:
public class Home {
private String mShortHomeName;
private String mLongHomeName;
private String mHomeDate;
private String mHomePrice;
public Home(String ShortName, String LongName, String Date, String Price) {
this.mShortHomeName = ShortName;
this.mLongHomeName = LongName;
this.mHomeDate = Date;
this.mHomePrice = Price;
}
public String getShortName() {
return this.mShortHomeName;
}
public String getLongName() {
return this.mLongHomeName;
}
public String getDate() {
return this.mHomeDate;
}
public String getPrice() {
return this.mHomePrice;
}
}
Added the following to my DatabaseHelper:
public Cursor getAllHomesAsCursor() {
SQLiteDatabase db = this.getWritableDatabase();
String[] columns = {"rowid as _id","*"};
return db.query(TABLE_NAME,columns,null,null,null,null,null);
}
The following to the activity that contains my listview:
DatabaseHelper db = new DatabaseHelper(getActivity());
Cursor csr = db.getAllHomesAsCursor();
HLAdapter adapter = new HLAdapter(getActivity(), csr);
listView.setAdapter(adapter);
The HLAdapter looks as follows:
public class HLAdapter extends CursorAdapter {
public HLAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
}
#Override
public View newView(Context context, Cursor csr, ViewGroup parent) {
return LayoutInflater.from(context).inflate(
R.layout.homelist_listview_layout,
parent,
false
);
}
#Override
public void bindView(View view, Context context, Cursor csr) {
TextView sname = (TextView) view.findViewById(R.id.homelist_name_short);
TextView lname = (TextView) view.findViewById(R.id.homelist_name_long);
TextView date = (TextView) view.findViewById(R.id.homelist_date);
TextView price = (TextView) view.findViewById(R.id.homelist_price);
sname.setText(csr.getString(csr.getColumnIndex("name_short")));
lname.setText(csr.getString(csr.getColumnIndex("name_long")));
date.setText(csr.getString(csr.getColumnIndex("date")));
price.setText(csr.getString(csr.getColumnIndex("price")));
}
}
My DatabaseHelper class looks as follows:
public class DatabaseHelper extends SQLiteOpenHelper{
public static final String DATABASE_NAME = "Main.db";
public static final String TABLE_NAME = "current_table";
public static final String COL_1 = "name_short";
public static final String COL_2 = "name_long";
public static final String COL_3 = "date";
public static final String COL_4 = "price";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, 1);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table " + TABLE_NAME + " (name_short TEXT,name_long TEXT, due_date TEXT, price TEXT) ");
}
#Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
public Cursor getAllHomesAsCursor() {
SQLiteDatabase db = this.getWritableDatabase();
String[] columns = {"rowid as _id","*"};
return db.query(TABLE_NAME,columns,null,null,null,null,null);
}
public boolean insertData(String name_short, String name_long, String due_date, String price) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COL_1,name_short);
contentValues.put(COL_2,name_long);
contentValues.put(COL_3,due_date);
contentValues.put(COL_4,price);
long result = db.insert(TABLE_NAME,null,contentValues);
if(result == -1)
return false;
else
return true;
}
public void deleteAllData() {
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL("DELETE FROM " + TABLE_NAME);
}
public Cursor getAllData() {
SQLiteDatabase db = this.getWritableDatabase();
Cursor res = db.rawQuery("SELECT * FROM " + TABLE_NAME ,null);
return res;
}
public Cursor getSpecifiedColumnData(String column) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery("SELECT column FROM " + TABLE_NAME,null);
return res;
}
}
I would think that my code should be working fine, but when I run the app. It closes immediately. Can you tell me what the problem is?
I believe the issue is that you need 4 String arrays to be passed to the adapter, so doing it like above you'd need to have a unique equivalent of getAllData for each type.
However considering that a house has a short name, long name, date and price a better approach could to consider all of these properties as an object and thus create a class. You could then create a List not of String objects but as a List of House objects, you'd be able to get them all in one go etc.
So (P.S. for the sake of my sanity I've incorporated the SO4522191 into the following so I can keep some sort of track of the code) :-
1) Create your Home Object to hold all values/properties of a house:-
1-a) Create a file the same as your home name, it's going to be a java class file.
In this case I've called it SO45422191Home, the code could be along the lines of :-
public class SO45422191Home {
private String mShortHomeName;
private String mLongHomeName;
private String mHomeDate;
private String mHomePrice;
public SO45422191Home(String ShortName, String LongName, String Date, String Price) {
this.mShortHomeName = ShortName;
this.mLongHomeName = LongName;
this.mHomeDate = Date;
this.mHomePrice = Price;
}
public String getShortName() {
return this.mShortHomeName;
}
public String getLongName() {
return this.mLongHomeName;
}
public String getDate() {
return this.mHomeDate;
}
public String getPrice() {
return this.mHomePrice;
}
}
Explanation
Using the above we can create a SO45422191Home object, in code elsewhere e.g. in your activity, by using something
like SO45422191Home Myhome = new SO45422191Home("Flower","Red
Rose","20-9-2017","1.50");.
With the MyHome object you can extract the properties e.g.
MyHome.getPrice() would return a String with a value of 1.50.
Similar for the other properties.
You can create an array of objects e.g. SO45422191Home[] homes = new
SO45422191Home[3]; will create an array of 3 (empty) SO45422191Home
objects. We could set the first element of the array using homes[0] =
new SO45422191Home("Bush","Cherry","11-10-2017","2.48");
2) Create a means of getting an array of SO45422191Home objects from the database.
here's some code for this:-
public List<SO45422191Home> getAllHomes() {
List<SO45422191Home> rv = new ArrayList<>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor csr = db.query(HOMETABLE,null,null,null,null,null,null);
while (csr.moveToNext()) {
SO45422191Home h = new SO45422191Home(
csr.getString(csr.getColumnIndex(SHORTHOMENAME)),
csr.getString(csr.getColumnIndex(LONGHOMENAME)),
csr.getString(csr.getColumnIndex(HOMEDATE)),
csr.getString(csr.getColumnIndex(HOMEPRICE))
);
rv.add(h);
}
csr.close();
return rv;
}
Explanation You used List and added elements to the list, List is similar but for SO45422191Home objects rather
than String objects.
The Database is opened, if not already open, using SQLiteDatabase db
= this.getWritableDatabase();.
All rows are extracted into a cursor.
The cursor is traversed each row at a time.
For each row a SO45422191Home object is created by getting the respective data from the cursor
(Note that csr.getColumnIndex(columnname) is used
rather than hard coding the column's index/offset, doing so can reduce
the chance for errors and also reduce overheads should changes be
applied.).
The the new object is added to the list.
Obviously column names would have to be adjusted, you may also want to add db.close() before the return.
3) Amend your adapter to take and use the the single list of objects rather than the 4 List.
here's an example adapter for use by a List (Note that R.layout.homeentry is the layout used for each entry in the ListView), the layout is below in the section re Cursor Adapter:-
public class AdapterHomeList2 extends ArrayAdapter {
List<SO45422191Home> homes;
LayoutInflater lInflater;
public AdapterHomeList2(Context context, List<SO45422191Home> homes) {
super(context,R.layout.homeentry, homes);
lInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.homes = homes;
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
View view = convertView;
if (view == null) {
view = lInflater.inflate(R.layout.homeentry, parent, false);
}
TextView sname = (TextView) view.findViewById(R.id.shortname);
TextView lname = (TextView) view.findViewById(R.id.longname);
TextView date = (TextView) view.findViewById(R.id.date);
TextView price = (TextView) view.findViewById(R.id.price);
sname.setText(homes.get(position).getShortName());
lname.setText(homes.get(position).getLongName());
date.setText(homes.get(position).getDate());
price.setText(homes.get(position).getPrice());
return view;
}
}
This is the code for an ArrayList :-
public class AdapterHomeList3 extends ArrayAdapter {
ArrayList<SO45422191Home> homes;
LayoutInflater lInflater;
public AdapterHomeList3(Context context, ArrayList<SO45422191Home> homes) {
super(context,R.layout.homeentry, homes);
lInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.homes = homes;
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
View view = convertView;
if (view == null) {
view = lInflater.inflate(R.layout.homeentry, parent, false);
}
TextView sname = (TextView) view.findViewById(R.id.shortname);
TextView lname = (TextView) view.findViewById(R.id.longname);
TextView date = (TextView) view.findViewById(R.id.date);
TextView price = (TextView) view.findViewById(R.id.price);
sname.setText(homes.get(position).getShortName());
lname.setText(homes.get(position).getLongName());
date.setText(homes.get(position).getDate());
price.setText(homes.get(position).getPrice());
return view;
}
}
Using a CursorAdapter
1) Add a new method to extract a cursor with all rows (NOTE! for cursor adapter a row named _id is required)
public Cursor getAllHomesAsCursor() {
SQLiteDatabase db = this.getWritableDatabase();
String[] columns = {"rowid as _id","*"};
return db.query(HOMETABLE,columns,null,null,null,null,null);
}
Note! instead of all columns i.e. coding null as the second parameter
to 'query' (which doesn't get the hidden rowid column (assuming
WITHOUT ROWID hasn't been used)), will will get the rowid (a unqiue
row identifier) and name this AS _id to suite the Cursor Adapter
hence "rowid as _id", the following * as the second element of
the columns array means all rows (specifying null as 2nd parameter
result in SELECT * .....).
Otherwise it's pretty simple. NOTE you must not close the database,
otherwise you can't access the cursor.
2) You will need a layout for each item in the list, as you would for a custom array adapter and it can be the same one i.e. there are no diferences according to which adapter is used. e.g. I created :-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/shortname"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/longname"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/date"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/price"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
</LinearLayout>
3) Create The Cursor Adpater as a class file, very similar to an Array Adapter.
public class AdapterHomeList extends CursorAdapter {
public AdapterHomeList(Context context, Cursor cursor) {
super(context, cursor,0);
}
#Override
public View newView(Context context, Cursor csr, ViewGroup parent) {
return LayoutInflater.from(context).inflate(
R.layout.homeentry, //<< layout for each list item
parent,
false
);
}
#Override
public void bindView(View view, Context context, Cursor csr) {
TextView sname = (TextView) view.findViewById(R.id.shortname);
TextView lname = (TextView) view.findViewById(R.id.longname);
TextView date = (TextView) view.findViewById(R.id.date);
TextView price = (TextView) view.findViewById(R.id.price);
sname.setText(csr.getString(csr.getColumnIndex(SO45422191.SHORTHOMENAME)));
lname.setText(csr.getString(csr.getColumnIndex(SO45422191.LONGHOMENAME)));
date.setText(csr.getString(csr.getColumnIndex(SO45422191.HOMEDATE)));
price.setText(csr.getString(csr.getColumnIndex(SO45422191.HOMEPRICE)));
}
}
Note! R.layout.homeentry being the layout for the list entries
and id's are from this.
4) From the respective activity, get the cursor, get an instance of the adapter and set the ListView to use the adapter.
e.g.:-
Cursor csr = dbhlp.getAllHomesAsCursor();
AdapterHomeList ahl = new AdapterHomeList(this,csr);
ListView hl = (ListView) this.findViewById(R.id.homelist);
hl.setAdapter(ahl);
result :-
Using cursor.getColumnIndex()
getColumnIndex
int getColumnIndex (String columnName)
Returns the zero-based index for the given column name, or -1 if the
column doesn't exist. If you expect the column to exist use
getColumnIndexOrThrow(String) instead, which will make the error more
clear.
SQLiteCursor
Using getColumnIndex as opposed to specifying the index removes the need to manually determine column offsets.
For example purposes, there is a table, named items with 3 columns, named as name, date and price :-
Using a query that uses the equivalent of SELECT * FROM items, the query will return a cursor with 3 columns, name, date and price
column name would have an offset of 0.
column date would have an offset of 1.
column price would have an offset of 2.
To extract the date from the cursor you could code cursor.getString(1);
However, if you were to have a query based upon SELECT date, price, name FROM items then the offsets would be:-
column name would have an offset of 2.
column date would have an offset of 0.
column price would have an offset of 1.
In this case you'd have to code cursor.getString(0); to extract the date.
It could be easy to inadvertently code the wrong offset, especially when using larger tables or when joining tables or when introducing generated columns.
Using cursor.getString(cursor.getColumnIndex("date")); could be used in both situations as it would return 1 in the first case and 0 in the second case.
Above, as an example, sname.setText(csr.getString(csr.getColumnIndex(SO45422191.SHORTHOMENAME))); has been coded.
Home.SHORTHOMENAME is a class varaible defined in the Database Helper (i.e. SO45422191 is the DatabaseHelper Class and SHORTHOMENAME is the class variable) that equates to the column name of the respective column as can be seen from the Database Helper code extract:-
public class SO45422191 extends SQLiteOpenHelper {
public static final String DBNAME = "SO45422191";
public static final String HOMETABLE = "homes";
public static final String SHORTHOMENAME = "shorthomename";
public static final String LONGHOMENAME = "longhomename";
public static final String HOMEDATE = "homedate";
public static final String HOMEPRICE = "homeprice";
// constructor
public SO45422191(Context context) {
super(context, DBNAME , null , 1);
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL("create table " + HOMETABLE +
"(" +
SHORTHOMENAME + " TEXT, " +
LONGHOMENAME + " TEXT, " +
HOMEDATE + " TEXT, " +
HOMEPRICE + ")");

Connecting to SQL server database with JavaFX [duplicate]

Can anyone give me one example of a class that connects JavaFX with MySQL, dont want Main class, have one, just want a example of a class that connects any application to a MySQL database and gets a row from that database into a table, searched the whole internet and i didn't find anything straight to the point i do not want anything fancy just something to get the job done please.
Something clean and simple.
At a minimum, you need three classes: one to represent your data, one for your UI, and one to manage the database connection. In a real app you'd need more than this, of course. This example follows the same basic example as the TableView tutorial
Suppose your database has a person table with three columns, first_name, last_name, email_address.
Then you would write a Person class:
import javafx.beans.property.StringProperty ;
import javafx.beans.property.SimpleStringProperty ;
public class Person {
private final StringProperty firstName = new SimpleStringProperty(this, "firstName");
public StringProperty firstNameProperty() {
return firstName ;
}
public final String getFirstName() {
return firstNameProperty().get();
}
public final void setFirstName(String firstName) {
firstNameProperty().set(firstName);
}
private final StringProperty lastName = new SimpleStringProperty(this, "lastName");
public StringProperty lastNameProperty() {
return lastName ;
}
public final String getLastName() {
return lastNameProperty().get();
}
public final void setLastName(String lastName) {
lastNameProperty().set(lastName);
}
private final StringProperty email = new SimpleStringProperty(this, "email");
public StringProperty emailProperty() {
return email ;
}
public final String getEmail() {
return emailProperty().get();
}
public final void setEmail(String email) {
emailProperty().set(email);
}
public Person() {}
public Person(String firstName, String lastName, String email) {
setFirstName(firstName);
setLastName(lastName);
setEmail(email);
}
}
A class to access the data from the database:
import java.sql.Connection ;
import java.sql.DriverManager ;
import java.sql.SQLException ;
import java.sql.Statement ;
import java.sql.ResultSet ;
import java.util.List ;
import java.util.ArrayList ;
public class PersonDataAccessor {
// in real life, use a connection pool....
private Connection connection ;
public PersonDataAccessor(String driverClassName, String dbURL, String user, String password) throws SQLException, ClassNotFoundException {
Class.forName(driverClassName);
connection = DriverManager.getConnection(dbURL, user, password);
}
public void shutdown() throws SQLException {
if (connection != null) {
connection.close();
}
}
public List<Person> getPersonList() throws SQLException {
try (
Statement stmnt = connection.createStatement();
ResultSet rs = stmnt.executeQuery("select * from person");
){
List<Person> personList = new ArrayList<>();
while (rs.next()) {
String firstName = rs.getString("first_name");
String lastName = rs.getString("last_name");
String email = rs.getString("email_address");
Person person = new Person(firstName, lastName, email);
personList.add(person);
}
return personList ;
}
}
// other methods, eg. addPerson(...) etc
}
And then a UI class:
import javafx.application.Application ;
import javafx.scene.control.TableView ;
import javafx.scene.control.TableColumn ;
import javafx.scene.control.cell.PropertyValueFactory ;
import javafx.scene.layout.BorderPane ;
import javafx.scene.Scene ;
import javafx.stage.Stage ;
public class PersonTableApp extends Application {
private PersonDataAccessor dataAccessor ;
#Override
public void start(Stage primaryStage) throws Exception {
dataAccessor = new PersonDataAccessor(...); // provide driverName, dbURL, user, password...
TableView<Person> personTable = new TableView<>();
TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstName"));
TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
lastNameCol.setCellValueFactory(new PropertyValueFactory<>("lastName"));
TableColumn<Person, String> emailCol = new TableColumn<>("Email");
emailCol.setCellValueFactory(new PropertyValueFactory<>("email"));
personTable.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
personTable.getItems().addAll(dataAccessor.getPersonList());
BorderPane root = new BorderPane();
root.setCenter(personTable);
Scene scene = new Scene(root, 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
#Override
public void stop() throws Exception {
if (dataAccessor != null) {
dataAccessor.shutdown();
}
}
public static void main(String[] args) {
launch(args);
}
}
(I just typed that in without testing, so there may be typos, missing imports, etc, but it should be enough to give you the idea.)
In addition to the answer of James_D:
I wanted to connect to a remote (MySQL) database, so I changed the constructor and connected by url-only:
public UserAccessor(String dbURL, String user, String password) throws SQLException, ClassNotFoundException {
connection = DriverManager.getConnection(dbURL, user, password);
}
Init via:
UserAccessor userAccessor = new UserAccessor(
"jdbc:mysql://xxx.xxx.xxx.xxx:YOUR_PORT", "YOUR_DB_USER", "YOUR_PASSWORD")
Please note:
You will also need to include the connector lib. I choosed mysql-connector-java-5.1.40-bin.jar which came with IntelliJ and was located under /Users/martin/Library/Preferences/IntelliJIdea2017.1/jdbc-drivers/MySQL Connector/J/5.1.40/mysql-connector-java-5.1.40-bin.jar
Kudos belong to James_D.

Resources