I have searched found a few answers but I am not quite sure I understand them. I want a multidimensional array or the equivalent of say string[0][1][1].
Here is what I have:
public List<List<List<String>>> loadCompleteExercises(String workout)
{
List<List<List<String>>> listExercises = new ArrayList<List<List<String>>>();
List<String> complete_time = new ArrayList<String>();
List<String> rest_time = new ArrayList<String>();
db = dbHelper.getReadableDatabase();
Cursor c = db.rawQuery("SELECT complete_time, rest_time FROM tbl_exercises WHERE workout = '"+workout+"';", null);
c.moveToFirst();
while(!c.isAfterLast()) {
try {
if(c.isNull(c.getColumnIndex("exercise"))) {
complete_time.add("00:00:05");
rest_time.add("00:00:00");
}else {
complete_time.add(c.getString(c.getColumnIndex("complete_time")));
rest_time.add(c.getString(c.getColumnIndex("rest_time")));
}
}catch (NullPointerException e)
{
Log.d("GET EXERCISES ERROR: ", e.toString());
}
c.moveToNext();
}
//listExercises.add();
return listExercises;
}
--- I want to add complete_time and rest_time to listExercises so that I can say do the following
listExercises.get(i).get(j) to yield the below
1 "00:00:05" "00:00:00"
2 "00:10:00" "00:10:00"
...
n "xx:xx:xx" "xx:xx:xx"
Try this, use a holder for both time, add them in a List
private class TimeHolder
{
public String completeTime;
public String restTime;
}
public List<TimeHolder> loadCompleteExercises(String workout)
{
List<TimeHolder> listExercises = new ArrayList<TimeHolder>();
db = dbHelper.getReadableDatabase();
Cursor c = db.rawQuery("SELECT complete_time, rest_time FROM tbl_exercises WHERE workout = '"+workout+"';", null);
c.moveToFirst();
while(!c.isAfterLast()) {
try
{
TimeHolder holder = new TimeHolder();
if(c.isNull(c.getColumnIndex("exercise"))) {
holder.completeTime = "00:00:05";
holder.restTime = "00:00:00";
}else {
holder.completeTime = c.getString(c.getColumnIndex("complete_time"));
holder.restTime = c.getString(c.getColumnIndex("rest_time"));
}
listExercises.add(holder);
}
catch (NullPointerException e)
{
Log.d("GET EXERCISES ERROR: ", e.toString());
}
c.moveToNext();
}
return listExercises;
}
Related
I created an Android application which uses the Google Books API. When I get the JSON response from the server, I parse the response and retrieve the title, authors, category, publisher, page count, thumbnail and some more information about the book. The problem is that some books in the JSON response don't have the thumbnail key or category key. When I try to get those JSON key values the program throws an error and consequently skips the code of adding other books after the error occurred.
I solved that with nested try catch blocks. For example, if there isn't a publisher key in the response, then I would return null.
String publisher;
try {
publisher = volumeInfo.getString("publisher");
} catch (JSONException e) {
publisher = null;
}
Here is how the whole method for parsing the JSON response looks like:
private List<BookData> parseJsonResponse(String jsonResponse) {
List<BookData> bookData = new ArrayList<>();
try {
JSONObject rootObject = new JSONObject(jsonResponse);
JSONArray itemsArray = rootObject.getJSONArray("items");
for (int i = 0; i < itemsArray.length(); i++) {
JSONObject itemObject = itemsArray.getJSONObject(i);
JSONObject volumeInfo =
itemObject.getJSONObject("volumeInfo");
String title;
try {
title = volumeInfo.getString("title");
} catch (JSONException e) {
title = null;
}
ArrayList<String> authors;
try {
JSONArray authorsArray =
volumeInfo.getJSONArray("authors");
authors = new ArrayList<>();
for (int j = 0; j < authorsArray.length(); j++) {
authors.add(authorsArray.getString(j));
}
} catch (JSONException e) {
authors = null;
}
ArrayList<String> categories;
try {
JSONArray categoriesArray =
volumeInfo.getJSONArray("categories");
categories = new ArrayList<>();
for (int k = 0; k < categoriesArray.length(); k++) {
categories.add(categoriesArray.getString(k));
}
} catch (JSONException e) {
categories = null;
}
String publisher;
try {
publisher = volumeInfo.getString("publisher");
} catch (JSONException e) {
publisher = null;
}
String publishedDate;
try {
publishedDate =
volumeInfo.getString("publishedDate");
} catch (JSONException e) {
publishedDate = null;
}
int pageCount;
try {
pageCount = volumeInfo.getInt("pageCount");
} catch (JSONException e) {
pageCount = 0;
}
String language;
try {
language = volumeInfo.getString("language");
} catch (JSONException e) {
language = null;
}
String description;
try {
description = volumeInfo.getString("description");
} catch (JSONException e) {
description = null;
}
String bookWebsite;
try {
bookWebsite = volumeInfo.getString("infoLink");
} catch (JSONException e) {
bookWebsite = null;
}
Bitmap thumbnail;
try {
JSONObject imageLink =
volumeInfo.getJSONObject("imageLinks");
String thumbnailUrl =
imageLink.getString("thumbnail");
thumbnail = getThumbnailBitmap(thumbnailUrl);
} catch (JSONException e) {
thumbnail = null;
}
// Add a new BookData object to the list
bookData.add(new BookData(title, thumbnail, authors,
categories, publisher, publishedDate,
pageCount, language, description,
bookWebsite));
}
} catch (JSONException e) {
Log.e(LOG_TAG, null, e);
}
return bookData;
}
After I complete my parsing, I have to update my views. I am using a list view, so the adapter needs to handle the views inflation.
I had to add an if statement to check if the variable is not null, then for example set the text of the text view. Else I set the text to "Publisher not available".
TextView publisher = listView.findViewById(R.id.book_publisher);
if (bookData.getPublisher() != null) {
publisher.setText(bookData.getPublisher());
} else {
publisher.setText("Publisher not available");
}
Here is how the whole adapter looks like:
public class BookDataAdapter extends ArrayAdapter<BookData> {
public BookDataAdapter(#NonNull Context context, #NonNull
List<BookData> bookDatas) {
super(context, 0, bookDatas);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView,
#NonNull ViewGroup parent) {
View listView = convertView;
if (listView == null) {
listView = LayoutInflater.from(getContext())
.inflate(R.layout.book_list_item, parent, false);
}
// Get current BookData object
BookData bookData = getItem(position);
ImageView thumbnail = listView.findViewById(R.id.book_thumbnail);
if (bookData.getThumbnail() != null) {
thumbnail.setImageBitmap(bookData.getThumbnail());
} else {
// Set default thumbnail
thumbnail.setImageResource(R.drawable.default_thumbnail);
}
TextView title = listView.findViewById(R.id.book_title);
if (bookData.getTitle() != null) {
title.setText(bookData.getTitle());
} else {
title.setText("Title not available");
}
TextView author = listView.findViewById(R.id.book_author);
if (bookData.getAuthors() != null) {
author.setText(listToString(bookData.getAuthors()));
} else {
author.setText("Authors not available");
}
TextView category = listView.findViewById(R.id.book_category);
if (bookData.getCategories() != null) {
category.setText("Category: " +
listToString(bookData.getCategories()));
} else {
category.setText("Category not available ");
}
TextView publisher = listView.findViewById(R.id.book_publisher);
if (bookData.getPublisher() != null) {
publisher.setText(bookData.getPublisher() + ", ");
} else {
publisher.setText("Publisher not available, ");
}
TextView publishedDate =
listView.findViewById(R.id.book_published_date);
if (bookData.getPublishedDate() != null) {
publishedDate.setText(bookData.getPublishedDate());
} else {
publishedDate.setText("Published date not available");
}
TextView pageCount = listView.findViewById(R.id.book_page_count);
if (bookData.getPageCount() != 0) {
pageCount.setText("Pages: " + bookData.getPageCount());
} else {
pageCount.setText("Page count not available");
}
TextView language = listView.findViewById(R.id.book_language);
if (bookData.getLanguage() != null) {
language.setText(bookData.getLanguage());
} else {
language.setText("Language not available");
}
TextView description =
listView.findViewById(R.id.book_description);
if (bookData.getDescription() != null) {
description.setText(bookData.getDescription());
} else {
description.setText("Description not available");
}
return listView;
}
private String listToString(List<String> list) {
if (list == null || list.size() == 0) {
return null;
}
StringBuilder builder = new StringBuilder();
for (int i = 0; i < list.size(); i++) {
builder.append(list.get(i));
if (i == (list.size() - 1)) {
break;
}
builder.append(", ");
}
return builder.toString();
}
}
And lastly I want to ask a question. Is there a better way or more efficient way of parsing the JSON response with different keys, because some people say that nested try catch statements are not a good practice?
Thank you very much!!
You have two options:
Using .has():
String publisher = null;
if(volumeInfo.has("publisher")){
publisher = volumeInfo.getString("publisher");
}
Using opt instead of get (better, IMO):
String publisher = volumeInfo.optString("publisher");
opt### methods default to null for objects and 0/false for primitives, so you don't have to write try/catch blocks or if conditions. You can also specify a second parameter as default value:
String publisher = volumeInfo.optString("publisher", "no publisher");
// if publisher is not a valid key, "no publisher" will be returned
Use can you .has() property of JSONObject
if(volumeInfo.has("publisher")){
volumeInfo.getString("publisher");
}
You don't need to wrap json operations in individual try/catch blocks.
There is a method in the json library to handle this problem:
jsonObject.isNull(key);
When you attempt to grab a value by key write it like this:
if (!volumeInfo.isNull("categories")) {
JSONArray categoryArray = volumeInfo.getJSONArray("categories");
}
I do not know how to get the data of two columns. I only know how to do it when it deals with one column only.
here is the code where the issue is:
public ArrayList<String> getData() {
ArrayList<String> List = new ArrayList<String>();
Cursor c = db.rawQuery("SELECT Column1, Column2 FROM Table where id = 1", null);
try {
if (c != null) {
if (c.moveToFirst()) {
do {
String levelData = c.getString(c.getColumnIndex("Column1"));
List.add("" + levelData);
}
while (c.moveToNext());
}
}
} catch (SQLiteException e) {
Log.e("Retrieve Data", "Unable to get Data " + e);
}
return List;
}
I know that the problem is at the c.getColumnIndex("Column1")); because that will be the place where to type the column of the table you want to get data from. But what will I do if I will try to do it using two columns?
the answer is simple. it was the first time i tried this and i didn't expect it to work so
this is what i did:
try {
if (c != null) {
if (c.moveToFirst()) {
do {
String levelData = c.getString(c.getColumnIndex("Column1"));
List.add("" + levelData);
}
while (c.moveToNext());
}
}
if (c != null) {
if (c.moveToFirst()) {
do {
String levelData = c.getString(c.getColumnIndex("Column2"));
List.add("" + levelData);
}
while (c.moveToNext());
}
}
} catch (SQLiteException e) {
Log.e("Retrieve Data", "Unable to get Data " + e);
}
I simply added another exact code but this time, it reads Column2 and worked as expected. :D
Make a java bean class with 2 variable and their getters & Setters like
public class Data {
String coloumn1;
String coloumn2;
public String getColoumn1() {
return coloumn1;
}
public void setColoumn1(String coloumn1) {
this.coloumn1 = coloumn1;
}
public String getColoumn2() {
return coloumn2;
}
public void setColoumn2(String coloumn2) {
this.coloumn2 = coloumn2;
}
}
Use
ArrayList dataList = new ArrayList();
dataList.setsetColoumn1(Your Data);
same for coloumn2 and for getters.
I'm getting this error :
E/AndroidRuntime(8223): Caused by: android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed. # Open Cursors=940 (# cursors opened by this proc=940)
I know its probably because I'm using the Cursor in a wrong way or not closing it at the right time. I think it could be because I'm filling the same cursor without closing/emptying it?
public static void NextAlarmTxt(){
int dan = c.get(Calendar.DAY_OF_WEEK);
long trenutnovrijeme = c.getTimeInMillis();
long bazavrijeme;
long pamti = 0;
String danString = dani(dan);
Cursor CursorDan = DatabaseManager.getAllDataDay(danString);
CursorDan.moveToFirst();
if (!CursorDan.isAfterLast())
{
do
{
bazavrijeme = CursorDan.getInt(2);
if (trenutnovrijeme<bazavrijeme)
{
if (pamti==0)
{
pamti = bazavrijeme;
}
if (pamti>0)
{
if (pamti > bazavrijeme)
{
pamti = bazavrijeme;
}
}
}
if (trenutnovrijeme > bazavrijeme)
{
dan = dan+1;
dani(dan);
CursorDan = DatabaseManager.getAllDataDay(danString);
}
}
while (CursorDan.moveToNext());
}
CursorDan.close();
text1.setText(new StringBuilder("Sljedeći : " ).append(pamti).toString());
}
public static String dani(int dan){
String danString = null;
if (dan==1)
{
danString = "Nedjelja";
}
else if (dan==2)
{
danString = "Ponedjeljak";
}
else if (dan==3)
{
danString = "Utorak";
}
else if (dan==4)
{
danString = "Srijeda";
}
else if (dan==5)
{
danString = "Četvrtak";
}
else if (dan==6)
{
danString = "Petak";
}
else if (dan==7)
{
danString = "Subota";
}
return danString;
}
Cursor Opened :
Cursor CursorDan = DatabaseManager.getAllDataDay(danString);
After that you iterate through the cursor,
do {
...
if (trenutnovrijeme > bazavrijeme)
{
dan = dan+1;
dani(dan);
CursorDan = DatabaseManager.getAllDataDay(danString);
}
....
}
while (CursorDan.moveToNext());
Now, with in the iteration loop, you overwrite the existing cursor with a new one, which leaves the existing one open. I am not sure what you are trying to achieve, but you should not be nesting cursor iteration this way and even if you do that, you should do it in a correct sequece.
Close existing cursor
Retrieve new cursor
Move new cursor to the first item by cursor.moveToFirst()
Please review the following piece of code:
try {
db.beginTransaction();
db.execSQL(DBConstants.PRAG_FOR_KEYS_ON);
db.execSQL(DBConstants._BLDG_CREATE);
db.execSQL(DBConstants._BLDG_INDEX);
for(int x = 0; x < 28; x = x+1){
db.execSQL(DBConstants._BLDG_INSERT+x);
}
db.execSQL(DBConstants.PRAG_FOR_KEYS_OFF);
db.setTransactionSuccessful();
} catch (SQLException e) {
e.printStackTrace();
}finally{
db.endTransaction();
}
Each of the insert constants (representing a row of new data) are numbered thus:
public static final String _BLDG_INSERT0 = "<SQL insert statement>"
...all the way up to 28 ("_BLDG_INSERT28").
Is there ANY way i can execute these SQL statements in a for loop? If i can, how do i concactenate the number on to the name of the constant AND have it recognized by the java interpreter in the correct way?
Thanks!
It's not clear from the question whether you are able to change the constants. If you can, it would be better if you could put the statements in an array.
String[] _BLDG_INSERT = {"<SQL insert statement>", // 0
"<SQL insert statement>", // 1
...
"<SQL insert statement>" // 28
};
And then you can just access them like this.
for(int x = 0; x < 28; x = x+1){
db.execSQL(DBConstants._BLDG_INSERT[x]);
}
Or better still:
for(String s : DBConstants._BLDG_INSERT) {
db.execSQL(s);
}
public ArrayList<String> getAllRecord()
{
ArrayList<String> total = new ArrayList<String>();
Cursor cursor1 = null;
try
{
cursor1 = getDBobject().rawQuery(
"select * from "
+ Your table name + ";", null);
if (cursor1.moveToFirst())
{
do
{
String cid = cursor1.getString(1);
total.add(cid);
}
while (cursor1.moveToNext());
}
}
catch (Exception e)
{
System.out.println("" + TAG + " :" + e);
}
finally
{
if (cursor1 != null && !cursor1.isClosed())
{
cursor1.close();
}
}
return total;
}
This will return you all the datas according to your insertion order
Try something like this:
public class testeReflection {
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException{
MyClass myClass = new MyClass();
Class aClass = MyClass.class;
for(int i = 0; i < 5; i++){
try {
Field field = aClass.getField("VAR" + i);
String s = (String)field.get(myClass);
System.out.println("myClass[" + i + "] = " + s);
} catch (NoSuchFieldException ex) {
Logger.getLogger(testeReflection.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
Logger.getLogger(testeReflection.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public static class MyClass{
public static final String VAR0 = "VARIAVEL 01";
public static final String VAR1 = "VARIAVEL 02";
public static final String VAR2 = "VARIAVEL 03";
public static final String VAR3 = "VARIAVEL 04";
public static final String VAR4 = "VARIAVEL 05";
}
}
i am using code this blog to have a draggable list. This tutorial is using a custom DragNDropAdapter
that takes the content as an ArrayList.
In my listActivity i query a table with returned column name.It has 11 values inserted.
i tried to convert it to ArrayList from String[] with many ways such as :
String[] from = new String[]{DbManager.KEY_NAME};
ArrayList<String> content = new ArrayList<String>();
for (int i=-1,l=from.length; ++i<l;) {
content.add(from[i]);
//Log.i("ArrayList", from[i]);
}
or
while(!mShopCatCursor.isAfterLast()){
content.add(mShopCatCursor.getString(0));
}
what i get is a list with just the name of the column, name.
do you have any ideas
You can use following method this method will get data from db and then return you an ArrayList of String for this data. In your case this array list will contain names.
private ArrayList<String> getArrayList() {
ArrayList<String> namesList = null;
Cursor cursor = null;
try {
String query = "";//your query here
cursor = db.rawQuery(query,null);
if (cursor != null && cursor.moveToFirst()) {
namesList = new ArrayList<String>();
do {
namesList.add(cursor.getString(0));
} while (cursor.moveToNext());
}
} catch (Exception e) {
e.printStackTrace();
namesList = null;
} finally {
if (cursor != null && !cursor.isClosed()) {
cursor.deactivate();
cursor.close();
cursor = null;
}
close();
}
return namesList;
}
/**
* Closes the database
*/
private void close() {
try {
if (db != null && db.isOpen()) {
DBHelper.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
String[] from = new String[]{DbManager.KEY_NAME};
Because your string array has only one value which is KEY_NAME.
What you need to do is,
Get values from Cursor using loop and populate it String[] above.
Cursor userCur = adaptor.getYourData();
if (userCur != null) {
String[] strArr = new String[userCur.getCount()];
startManagingCursor(userCur);
if (userCur.moveToFirst()) {
int count = 0;
do {
String userName = userCur.getString(1);
strArr[count] = userName.trim();
count++;
} while (userCur.moveToNext());
}
ArrayList<String> content = new ArrayList<String>();
for (int i=-1,l=from.length; ++i<l;) {
content.add(from[i]);
//Log.i("ArrayList", from[i]);
}
}
Note: I haven't validated this in IDE, there may be syntax errors.