Caught in an infinite loop - java

I'm trying to perform a check on some information in a database. If i run the following code without it being in a loop it runs fine, but only checking the first row, what i need it to do is to check the names and dates for each row.
If i understand the while loop correctly it would move my cursor to the next row then just run the code again. Can anyone see why this is looping until my program crashes?
while (cursor.moveToNext()) {
String titlefromdb = cursor.getString(3);
if (strTitle.equals(titlefromdb)&& cursor.getString(1).equals(dateselforap)) {
Log.d("insidematch", "date and title matched");
final Dialog matchdiag = new DialogCW2Organisor.this);
matchdiag.setContentView(R.layout.apptmatch);
matchdiag.setTitle("View/Edit Appointment");
matchdiag.setCancelable(true);
TextView matchtxt = (TextView) matchdiag.findViewById(R.id.matchtxt);
matchtxt.setText("Appointment \""+ titlefromdb + "\" already exists, please choose a different event title");
Button btnmatchok = (Button) matchdiag.findViewById(R.id.btnmatch);
btnmatchok.setOnClickListener(new OnClickListener() {
//on click for cancel button
#Override
public void onClick(View v) {
matchdiag.dismiss();}
});
matchdiag.show();
} else {
addAppt(strTime, strTitle, strDet);
cursor = getAppts();
dialog.dismiss();
}
}

Try moving to the first record before calling moveToNext().
Move your functionality into a do/while loop so you can still grab the first record
if (!cursor.moveToFirst())
return; //nothing to do since the cursor is empty
do
{
String titlefromdb = cursor.getString(3);
if (strTitle.equals(titlefromdb)&& cursor.getString(1).equals(dateselforap)) {
Log.d("insidematch", "date and title matched");
final Dialog matchdiag = new DialogCW2Organisor.this);
matchdiag.setContentView(R.layout.apptmatch);
matchdiag.setTitle("View/Edit Appointment");
matchdiag.setCancelable(true);
TextView matchtxt = (TextView) matchdiag.findViewById(R.id.matchtxt);
matchtxt.setText("Appointment \""+ titlefromdb + "\" already exists, please choose a different event title");
Button btnmatchok = (Button) matchdiag.findViewById(R.id.btnmatch);
btnmatchok.setOnClickListener(new OnClickListener() {
//on click for cancel button
#Override
public void onClick(View v) {
matchdiag.dismiss();
}
});
matchdiag.show();
} else {
addAppt(strTime, strTitle, strDet);
cursor = getAppts();
dialog.dismiss();
}
} while (cursor.moveToNext());

I have also run into the infinite loop problem, which really baffled me as well, since a while !moveToNext() loop should definitely finish.
However, the workaround is to use a for loop over the length of the cursor, and process each cursor.moveToPosition(i).
for (int i = 0; i <= cursorLen; i++) {
if (!cursor.moveToPosition(i)) {
return;
}
// process your cursor
}
I feel like this must be a bug with the Cursor implementation, because a while loop over cursor.moveToNext() should always finish.

Related

Display a SQLite colum one value after another

I'm really strugling to figure this out and had not found an answer or a way to do it.
What I'm trying to do is having questions that are saved in a SQLite colum to be displayed in a TextView one after another until they finish.
What I have done so far on the main Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDatabaseHelper = new DatabaseHelper(this);
btn1star = (Button) findViewById(R.id.btn1star);
btn2star = (Button) findViewById(R.id.btn2star);
btn3star = (Button) findViewById(R.id.btn3star);
mListview = (ListView) findViewById(R.id.qlistview);
qTextView = (TextView) findViewById(R.id.qTextView);
questionsListView();
}
private void questionsListView() {
Cursor data = mDatabaseHelper.getData();
data.moveToFirst();
qTextView.setText(data.getString(1));
}
public void VoteClick(View view){
mDatabaseHelper.getReadableDatabase();
Cursor data = mDatabaseHelper.getData();
if (data.getCount() >=1){
for (int i = 0; i< data.getCount(); i++) {
data.moveToNext();
Log.i("Counted Questions are: ", String.valueOf(data.getCount()));
qTextView.setText(data.getString(1));
}
}
}
private void toastmessage (String message){
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
I'm able to display the first and when i click the button the last question
I'm unable to display the questions between.
Any tip or suggestion?
In your VoteClick method you do your getReadableDatabase, this is too late, move this line into onCreate method. You must open the database before reading from it (in questionsListView).
mDatabaseHelper.getReadableDatabase();//move to onCreate
add this:
startManagingCursor(data);
data.moveToFirst();
BEFORE the line:
if (data.getCount() >=1){
Hello found a solution to my problem
It turns out that i have to make a new int variable
Get its value from the first id
and incrise this by one at the end of each button press until i reach the last cursor place whhere i move the cursor to the first position
public void VoteClick(View view) {
Cursor data = mDatabaseHelper.getData();
data.moveToPosition(q);
data.moveToNext();
qTextView.setText(data.getString(1));
while (data.isLast()) {
data.moveToFirst();
q = data.getPosition();
}
q = q+1;
}

How to get id from dynamically added checkbox and them value

I want to get value for dynamically added CheckBox but when i want to see if one of my checkBox.isChecked(); it only respond when i check the last checkbox created ! Here is my container.
for (String answer : multiMap.get(questionFromMultiMap))
{
i++;
et_button = (CheckBox) getLayoutInflater().inflate(R.layout.numberofchoices, null);
et_button.setText(answer);
et_button.setId(i);
container.addView(et_button);
listOfChoice.add(answer);
}
I want to check it's checked like that :
btnCorrect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (et_button.isChecked()){
System.out.println(et_button.getId());
}else{
System.out.println("pouet");
}
}
});
Didn't find right answer on google !
Thanks for help
When you call et_button.isChecked() this is called on the last inflated view, cause you are overwriting it every iteration of the loop.
You should add them in a List instead, and then in the onClickListener check which one is checked:
List<CheckBox> list = new LinkedList<>(); //this should be visible from onClickListener, so it should be an instance field
for (String answer : multiMap.get(questionFromMultiMap)) {
i++;
CheckBox et_button = (CheckBox) getLayoutInflater().inflate(R.layout.numberofchoices, null);
et_button.setText(answer);
et_button.setId(i);
list.add(et_button);
container.addView(et_button);
listOfChoice.add(answer);
}
btnCorrect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for(CheckBox cb : list) {
if (cb.isChecked()){
System.out.println(cb.getId());
}else{
System.out.println("pouet");
}
}
}
});
Haven't tested it but It should work.

EditText to Integer (Android)

I am attempting to convert an EditText, which is of type number in xml, to an Integer in order to calculate the value in seconds.
hoursIn = (EditText) findViewById(R.id.hoursET);
minIn = (EditText) findViewById(R.id.minET);
start = (Button) findViewById(R.id.startButton);
stop = (Button) findViewById(R.id.stopButton);
textViewTime = (TextView) findViewById(R.id.timeDisp);
inHr = Integer.parseInt(hoursIn.getText().toString());
inMin = Integer.parseInt(minIn.getText().toString());
hoursMs = hrsToMs(inHr);
minMs = minToMs(inMin);
totalTime = hoursMs + minMs;
When I comment the lines where inHr and inMin are initialized I get no error in runtime, however when I leave the code as it is above I get the following error:
java.lang.RuntimeException: Unable to start activity ComponentInfo{dit.assignment3/dit.assignment3.Timer}: java.lang.NumberFormatException: Invalid int: ""
I have also attempted this while getting the same error starting at the same line of code:
final CounterClass timer = new CounterClass(totalTime, 1000);
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (hoursIn != null)
{
inHr = Integer.parseInt(hoursIn.getText().toString());
hoursMs = hrsToMs(inHr);
}
if (minIn != null)
{
inMin = Integer.parseInt(minIn.getText().toString());
minMs = minToMs(inMin);
}
else
{
textViewTime.setText("PLEASE GIVE A TIME");
}
totalTime = hoursMs + minMs;
timer.start();
}
});
Thanks in advance :)
I'm certain that this codes blocks are exactly same as you've shown here. That means You are directly initializing EditText and immediately calling getText() method which causes Exception.
There wont be any value immediately after initialization so that you are getting NumberFormatException when calling Integer.parseInt to empty value.
So I suggest you to put these codes inside some event like buttonClicked like here, so that you can be sure that you've entered some texts. And It's better checking if empty as well,
public void buttonClicked(View v){
inHr = Integer.parseInt(hoursIn.getText().toString());
inMin = Integer.parseInt(minIn.getText().toString());
}
You will get an java.lang.NumberFormatException: Invalid int: "" whenever you try to parse an empty string to Integer. Thus you need to check whether the EditText is empty or not.
You could easily do that as below
if (hoursIn.getText().toString().matches("")) {
Toast.makeText(this, "You did not enter a text", Toast.LENGTH_SHORT).show();
return;
}
OR
you can simply do a check as below
if (hoursIn.getText().toString().equals("")) {
Toast.makeText(this, "You did not enter a text", Toast.LENGTH_SHORT).show();
return;
}
First you have to put the lines where you are reading from edittext inside some event like click of a button. Then check whether anything is entered in the edittext or not, then use try/catch clause to convert it into number.
Try this code.
Add a button to your activity xml file:
<Button
android:height="wrap_content"
android:width="wrap_content"
android:onClick="myClickHandler" />
hoursIn = (EditText) findViewById(R.id.hoursET);
minIn = (EditText) findViewById(R.id.minET);
start = (Button) findViewById(R.id.startButton);
stop = (Button) findViewById(R.id.stopButton);
textViewTime = (TextView) findViewById(R.id.timeDisp);
public void myClickHandler(View v){
if (hoursIn.getText().toString().matches("") || minIn.getText().toString().matches("")){
Toast.makeText(this, "You did not enter a text",Toast.LENGTH_SHORT).show();
return;
} else {
try {
inHr = Integer.parseInt(hoursIn.getText().toString());
inMin = Integer.parseInt(minIn.getText().toString());
hoursMs = hrsToMs(inHr);
minMs = minToMs(inMin);
totalTime = hoursMs + minMs;
Log.i("success");
} catch (NumberFormatException e) {
Toast.makeText(this, "Please enter number only",Toast.LENGTH_SHORT).show();
return;
}
}
}

Retrieving data and passing to textview

I'm trying to think of the logic behind how I should do this. The way I am doing it right now is sort of a hack, but it works. It's just too many API requests and unnecessary, so hopefully someone here can help me envision on how I should do this.
I'm using the parse.com SDK for android to retrieve data to display videos.
Here is my code for the video function
int count = 9;
private void getVideos()
{
ParseQuery<ParseObject> query = ParseQuery.getQuery("Videos");
query.whereEqualTo("videoid", count);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> videoData, ParseException e) {
if (e == null) {
/** check to see if there are any more videos **/
if(videoData.size() == 0){
Toast.makeText(getApplicationContext(), "No more videos found.", Toast.LENGTH_LONG).show();
}else{
for(int i=0; i<videoData.size(); i++){
String videoUrl = videoData.get(i).getString("url");
String videoTitle = videoData.get(i).getString("title");
String videoUser = videoData.get(i).getString("user");
TextView title = (TextView)findViewById(R.id.videoTitle);
title.setTextColor(Color.parseColor("#FFFFFF"));
title.setText(videoTitle);
TextView user = (TextView)findViewById(R.id.videoUser);
user.setTextColor(Color.parseColor("#FFFFFF"));
user.setText("By: " + videoUser);
myVideoView = (VideoView) findViewById(R.id.myvideoview);
myVideoView.setVideoPath(vineVideoUrl);
myVideoView.setMediaController(null);
myVideoView.start();
/** loop video **/
myVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
myVideoView.start();
}
});
/** next video **/
Button button= (Button) findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
count++;
Toast.makeText(getApplicationContext(), "Loading...", Toast.LENGTH_LONG).show();
getVideos();
}
});
}
}
} else {
Toast.makeText(getApplicationContext(), "Unable to retrieve videos, please check back later.", Toast.LENGTH_LONG).show();
}
}
});
}
Each time the button is pressed, it increments count, and gets the video for that ID from the API. What I am trying to figure out is how can I retrieve say the latest 20 videos from the API the correct way?
The way I can think the proper way to do it is this:
Get latest 20 videos from API, store in array, then when button is pressed loop thru each. How would I pass them each to the textview? And how should I know when it's the last video (20) and to call the API again and pass back the new results?
You can create a List<String> oldMovies which will hold the ids of the movies you already received, now each time you want bring more movies in your query add this constraint movieQuery.notConteindIn("onjectId", oldMovies). That shall return a list of movies that doesn't have one of the objectsId contained in the oldMovies. Each time you will need to update the oldMovie list of ids.

getting next value in android using SQLite

I have doing small application in android.During this application, i have suffer this problem:
I search the keyword using "oh" then i listing in to listview using this code.
nameList.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
try {
Intent intent = new Intent(Search.this,
SearchDetails.class);
/*
* Cursor cursor = (Cursor) adapter.getItem(position);
* intent.putExtra("JOK_ID",
* cursor.getInt(cursor.getColumnIndex("_id")));
*/
intent.putExtra("id", id);
intent.putExtra("position", position);
Log.d(TAG, " I.." + id);
Log.d(TAG, " P.." + position);
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
for example like this
Now, if I click oham then display just like this:
Finally, I want to , If i click previous button then display john and Next to display krackohm. And count total number of searched names.
I have try this code for next button:
Cursor cursor = db.rawQuery("SELECT _id, name FROM std WHERE _id = ?",
new String[]{""+Id});
if (cursor.getCount() == 1)
{
cursor.moveToFirst();
...body
}
Edit:
This is first time when any list item click, on create
private void dislpayFirstName() { // this is display first time click list item
writeDatabase();
cursor = db.rawQuery("SELECT _id, name FROM std WHERE._id = ?",
new String[]{""+Id});
if (cursor.getCount()> 0)
{
cursor.moveToFirst();
nameDetails();
}
}
This is the code for Next Button click:
position++;
writeDatabase();
cursor = db.rawQuery("SELECT _id,name FROM std", null);
if (cursor.getCount()> 0)
{
cursor.moveToPosition(position);
//cursor.moveToNext();
nameDetails();
}
In next button: If cursor.moveToPosition(position); then next name display matching position and table id. Means postion 2 then display 2 number name from table.
In next button: If cursor.moveToNext(); then next name display beginning of table.Means 0 id name from table.
You have to do it like this:
Cursor cursor = db.rawQuery("SELECT _id, name FROM std") // get all rows
Than, to display you first entry:
cursor.moveToFirst();
displayData(); // Method to display the data from the cursor on screen
Clicking you "next" Button:
if (cursor.moveToNext()){ // moveToNext returns true if there is a next row
displayData();}
And equally: with your "previous"Button use cursor.moveToPrevious()
Put cursor.moveToFirst(); at first. I mean put it like this..
cursor.moveToFirst();
if(your condition)
{
}
Instead of using id as extra with intent,you should use the position of the item in list.
The position will be similar to the position of the same record in your cursor so you just need to move your cursor to that position and fetch the detail you need from the same.Then you can display it on activity,as you have shown on your second activity view.
so in your SearchDetails.class,you need to do:
...
int position=getIntent.getIntExtra("position",999); // 999 is default value
Cursor cursor = db.rawQuery(<query which you fired for populating search results in previous activity>);
if (cursor.getCount()> 0 && position!=999){
cursor.moveToPosition(position);
...body // fetch details and display it.
}
backButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
position--;
//display details code
Cursor cursor = db.rawQuery(<query which you fired for populating search results in previous activity>);
if (cursor.getCount()> 0 && position!=-1){
cursor.moveToPosition(position);
...body // fetch details and display it.
}
}
}
nextButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
position++;
//display details code
Cursor cursor = db.rawQuery(<query which you fired for populating search results in previous activity>);
if (cursor.getCount()> 0 && position!=cursor.getCount()){
cursor.moveToPosition(position)
...body // fetch details and display it.
}
}
}
...
EDIT :
Revised code: ( repeated code removed)
...
int position=getIntent.getIntExtra("position",999); // 999 is default value
Cursor cursor = db.rawQuery(<query which you fired for populating search results in previous activity>);
if (cursor.getCount()> 0 && position!=999){
cursor.moveToPosition(position);
...body // fetch details and display it.
}
backButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
position--;
if (position!=-1){
cursor.moveToPosition(position);
...body // fetch details and display it.
}
}
nextButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
position++;
if (position!=cursor.getCount()){
cursor.moveToPosition(position)
...body // fetch details and display it.
}
}
}
...

Categories

Resources