Android: IndexOutOfBounds Error when deleting row in ListView - java

I have an application that has 2 screens. The first screen has a ListView of movies with a row consisting of 3 Elements: Title, Date and Gross declared in strings.xml. The user has the option of adding a movie by clicking the menu button, which sends him to another screen. The second screen has 3 Edit texts that correspond to Title Date and Gross, which is alphabetically sorted straight away when it returns to screen 1.
Similarly, the user can also Edit/Delete entries by long clicking a row thatbrings up a context menu. The Edit function works like this:
a.) User long clicks Titanic and chooses Edit
b.) Row gets deleted, and user is brought to screen 2
c.) Edit texts are populated with the initial data from the deleted Row
d.) When user edits data, new movie is added at the bottom of the ListView.
The problem arises when the user deletes this new movie at the bottom of the ListView. Logcat gives a
java.lang.IndexOutOfBoundsException: Invalid index 50, size is 50
Here is my code (Take note I am using Perst to persist data, but I don;t think that won't really matter with my problem):
case R.id.contextedit:
Lab9_082588FetchDetails row = (Lab9_082588FetchDetails) getListView()
.getItemAtPosition(info.position);
Intent editData = new Intent(MovieList.this, Lab9_082588Edit.class);
String startTitle = row.getTitle();
String startGross = row.getGross();
String startDate = row.getDate();
editData.putExtra(Lab9_082588Edit.TITLE_STRING, startTitle);
editData.putExtra(Lab9_082588Edit.GROSS_STRING, startGross);
editData.putExtra(Lab9_082588Edit.DATE_STRING, startDate);
startActivityForResult(editData, MovieList.EDIT_MOVIE);
int posEdit = info.position;
String editTitle = results.get(info.position).getTitle();
results.remove(posEdit);
adapter.notifyDataSetChanged();
//Perst
Index<Lab9_082588FetchDetails> rootEdit = (Index<Lab9_082588FetchDetails>) db
.getRoot();
rootEdit.remove(editTitle, results.get((int) info.id));
db.setRoot(rootEdit);
return true;
Edit Class:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection using item.getItemId()
switch (item.getItemId()) {
case R.id.edit:
next();
break;
}
return true;
}
private void next() {
// TODO Auto-generated method stub
EditText movieTitle = (EditText) findViewById(R.id.etTitle);
EditText movieGross = (EditText) findViewById(R.id.etGross);
EditText movieDate = (EditText) findViewById(R.id.etDate);
String title = movieTitle.getText().toString();
String gross = movieGross.getText().toString();
String date = movieDate.getText().toString();
if ((title.length() > 0) && (gross.length() > 0)
&& (date.length() == 4)) {
Intent hobby = getIntent();
hobby.putExtra(Lab9_082588Edit.TITLE_STRING, title);
hobby.putExtra(Lab9_082588Edit.GROSS_STRING, gross);
hobby.putExtra(Lab9_082588Edit.DATE_STRING, date);
setResult(RESULT_OK, hobby);
finish();
}
}
Delete function:
int posDelete = info.position;
String deleteTitle = results.get(
info.position).getTitle();
results.remove(posDelete);
adapter.notifyDataSetChanged();
Index<Lab9_082588FetchDetails> rootDelete = (Index<Lab9_082588FetchDetails>) db
.getRoot();
rootDelete.remove(deleteTitle,
results.get(info.position));
db.setRoot(rootDelete); //Perst
return;
OnActivityResult (Edit):
case EDIT_MOVIE:
Lab9_082588FetchDetails edittedMovie = new Lab9_082588FetchDetails();
NumberFormat formatterEdit = new DecimalFormat("###,###,###");
edittedMovie.setTitle(data
.getStringExtra(Lab9_082588Add.TITLE_STRING));
edittedMovie.setGross("$"
+ formatterEdit.format(Double.parseDouble(data
.getStringExtra(Lab9_082588Add.GROSS_STRING))));
edittedMovie.setDate(data
.getStringExtra(Lab9_082588Add.DATE_STRING));
results.add(edittedMovie);
adapter.notifyDataSetChanged();
Populating the Listview:
for (int i = 0; i < items.size(); i++) {
Lab9_082588FetchDetails sr = new Lab9_082588FetchDetails();
sr.setTitle(items.get(i).getTitle());
sr.setGross(items.get(i).getGross());
sr.setDate(items.get(i).getDate());
results.add(sr);
Collections.sort(results, ignoreCaseStart);
}
How do I remedy this?

This problem occurs because in your delete function, you first remove the element from the results collection("results.remove(posDelete);"), and then, a few lines later, you call "results.get(info.position)" to fetch a parameter for the rootDelete.remove call, but which is already removed.
If the element is the last element of your collection, let's say the 50th element, the value for "info.position" is 50. You remove one element, so the number of elements is now 49. In the rootDelete.remove line you call results.get(50), which produces the error.

Related

delete/modify selected text in EdiText in android

I entered text in an EditText while designing a form filling app. Now, if i select part of that text, and wish to delete/modify it, I am not getting how to do it. All other options show how to clear entire textbox. How to clear just selected text.
EditText inputText=(EditText)findViewById(R.id.edit);
String inputString=inputText.getText().toString();
//To get the selected String
int selectionStart=inputText.getSelectionStart();
int selectionEnd=inputText.getSelectionEnd();
String selectedText = inputString.substring(selectionStart, selectionEnd);
if(!selectedText.isEmpty())
{
//Modify the selected StringHere
String modifiedString="...your modification logic here...";
//If you wish to delete the selected text
String selectionDeletedString=inputString.replace(selectedText,"");
inputText.setText(selectionDeletedString);
//If you wish to modify the selected text
String selectionModifiedString=inputString.replace(selectedText,modifiedString);
inputText.setText(selectionModifiedString);
}
You need to extract the string with
String fromEditText = editText.getText();
Now, you can do with string whatever you want and then put it back like
editText.setText(myString);
For operations with strings google working with strings and chars java on google.
Try this..
public void modifyText(View view ) {
if (view instanceof EditText) {
if(view.getText().toString().equals("Selected text")){
view.setText("Your Text");
}
}
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
View innerView = ((ViewGroup) view).getChildAt(i);
modifyText(innerView);
}
}
}
call this in your activity modifyText(findViewById(R.id.rootView));
This will modify all EditText in the current activity
I found this to be the best solution.
String contents = editText.getText().toString(), newText;
newText = contents.substring(0, noteEdit.getSelectionStart()) +
contents.substring(editText.getSelectionEnd(), contents.length());
editText.setText(newText);
Edit Selection
An easy and best(maybe) way of modifying the selected text.
int start = descriptionBox.getSelectionStart();
int end = descriptionBox.getSelectionEnd();
String modifiedText = "*" + descriptionBox.getText().subSequence(start, end) + "*";
descriptionBox.getText().replace(start, end, modifiedText);
Input Text ( '|' indicate selection )
hello |world|
Output Text
hello *world*
Delete Selection
All you have to do is replace the start and end of selection with empty String.
int start = descriptionBox.getSelectionStart();
int end = descriptionBox.getSelectionEnd();
descriptionBox.getText().replace(start, end, "");

Couldn't get text from the textfield Java

I have encounter a problem with my if else statement. I can't execute my if else statement. Actually the program should get the text from the text field and then convert to integer and validate whether the item id is found or not.
below is my partial coding:
Integer itmID = new Integer(inputItemID.getText());
Integer brwID = new Integer(inputBorrowerID.getText());
Item itm = parent.getItems().get(itmID);
Borrower brw = parent.getBorrowers().get(brwID);
if (itm == null) {
JOptionPane.showMessageDialog(this, "Item ID not found","Error", JOptionPane.ERROR_MESSAGE);
return;
}
You are retrieving item like Item itm = parent.getItems().get(itmID); , i assume that getItems() is some kind of collection . You are getting itm = null because your getItems() doesn't contain any item with given itemId.

Android crashes when try to overwrite TextViews

I've created a timetable app, which allows the user to enter data and then view it.However if the user enters an entry, on a day and time where there already is one, my emulator crashes(forces a close).
Basically I'm pulling back data to a linear layout- which contains 10 TextViews, each representing the times 9-15.
Here's the code:
public void addMondayGrid() {
// TODO Auto-generated method stub
for (int index = 0; index < info.mon.size(); index++) {
// int entryId = info.monIds.get(index);
int time = info.monTimes.get(index);
int id = info.monIds.get(index);
int duration = info.monDuration.get(index);
String dayOfWeek = "mon";
timeId = getResources().getIdentifier("mon" + time, "id",
getPackageName());
if (duration == 1) {
SpannableString text = new SpannableString(info.mon.get(index));
setEntryColour(text);
final TextView textV = (TextView) findViewById(timeId);
textV.setTextSize(10);
textV.setText(text, BufferType.SPANNABLE);
textV.setId(id);
deleteGridEntry(textV);
} else {
longerDuration(time, index, id, info.mon, dayOfWeek);
}
}
}
The thing is is works fine as long as there isn't two entries for the same day and time, eg. monday at 9 oclock.
Anyone have any ideas?I'm quite new to this and any help would be much appreciated!
I have to reference the id this way as there are too many ids to reference any other way,is there not a simple way to overwrite the old textView with new data pulled back from the database? I want the id to be the same one as that is the textView I want to deal with, but it just keeps crashing, is it something to do with instances?
change:
final TextView textV = (TextView) findViewById(timeId);
to:
final TextView textV = (TextView) findViewById(R.id.timeId);

android xml node parse array adapter weird

I have an odd problem, (see shorter version at the bottom first please)
When my activity starts for the first time, the listview shows the dataset fine. The adapter is a custom adapter which shows 2 rows of text and an image. I call an asynctask upon a click event to the listview, the dataset updates in accordance with whatever was clicked on in the listview - more specifically the arrays which are associated with the adapter become rewritten with the parsings of some xml, and then notifyachapterdatasetchanged method is called to update the listview in the onPostExecute function. However I always get NullPointerException when I am iterating through some xml (which is very well formed and validates). ALso its worth mentioing that the algorithm that parses the desired values is good, because as mentioned above, if i write to just 1 element of the array then I dont get the error I just get the last node value so its looping in the correct places. i.e If I simple try to copy the current node value I am parsing during the loop into, say, producyTypes[0] then the last value from within the loop actually makes it to the listview as it constantly overwrites this elemet of the array
Here is my code.`
public class main extends Activity implements OnItemClickListener
{
String selectedType="";
ListView lview3;
ImageView iv;
ListViewCustomAdapter adapter;
String test = "";
List<String> ls;
String productTypes[] = {"Monitor","Components","Systems","Laptops","Flash / Usb Memory",
"Networking","Cables","Peripherals","Sound and Vision", "Software"};
String productsIncluded[] = {"Sizes (inches) 17, 19, 20",
"Motherboards, PSU, Cases, Fans/Heatsinks/Coolers, Barebones Systems, Blue-Ray/DVD. Card Readers, Controller Cards, Drive Enclosures, Sound Cards",
"Bundles, Switches and Hubs, Print Servers, Accessories/Modules",
"Cables for: Drives, Networking, HDMI/Monitor, Audio/Video, USB/Firewire, Power, Miscellaneous",
"Mice, Connectors, Bluetooth Devices",
"Mp3/Mp4 Solar Panel",
"Anti-Virus, Internet Security, Operating Systems, Office,,
"",
""};
private static int images[] = {R.drawable.monitor, R.drawable.components, R.drawable.systems,
R.drawable.laptops, R.drawable.flashusb, R.drawable.networking, R.drawable.cables, R.drawable.
peripherals, R.drawable.soundandvision, R.drawable.software};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
iv = (ImageView)findViewById(R.id.ImageView01);
iv.setImageResource(R.drawable.logo);
iv.setVisibility(View.VISIBLE);
lview3 = (ListView) findViewById(R.id.listView3);
adapter = new ListViewCustomAdapter(main.this, productTypes, productsIncluded, images);
lview3.setAdapter(adapter);
lview3.setOnItemClickListener(main.this);
}
#Override
public void onItemClick(AdapterView arg0, View arg1, int position, long id) {
selectedType = "";
if(position == 0)
{
selectedType= "Monitors";
}
if(position == 1)
{
selectedType= "Hard Drives";
}
Toast.makeText(this, Integer.toString(position), Toast.LENGTH_SHORT).show();
new async().execute();
/*
Intent intent = new Intent(getApplicationContext(),activitywo.class);
Bundle bundle =new Bundle();
bundle.putString("selectedType",selectedType);
intent.putExtras(bundle);
startActivity(intent);
//Toast.makeText(this, "Title => "+productTypes[position]+" \n Description => "+productsIncluded[position], Toast.LENGTH_SHORT).show();
*/
}
private class async extends AsyncTask<String, Void, Void> {
// UI Thread
protected void onPreExecute() {
}
// automatically done on worker thread (separate from UI thread)
protected Void doInBackground(final String... args) {
try{
Resources res = getResources();
InputStream in;
in = res.openRawResource(R.raw.core);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document dom = builder.parse(in);
Element root = dom.getDocumentElement();
NodeList items = root.getElementsByTagName("entry");
count=0;
for(int i =0;i<items.getLength();i++){
Node item = items.item(i);
NodeList properties = item.getChildNodes();
//productsDefinedByTypeArray = new String[properties.getLength()];
for(int j = 0;j<properties.getLength();j++){
Node property = properties.item(j);
String name = property.getNodeName();
if(name.equalsIgnoreCase("g:product_type")){//everytime we hit g:product_type grab the value
String strText = property.getFirstChild().getNodeValue();
if(strText.contains(selectedType)){
//
for(int k = 0;k<properties.getLength();k++){
Node propertysecond = properties.item(k);
String namesecond = propertysecond.getNodeName();
if(namesecond.equalsIgnoreCase("title")){//everytime we hit title grab the value
String strTextsecond = propertysecond.getFirstChild().getNodeValue();
productTypes[0] = strTextsecond;
yo = strTextsecond;
count++;
}
}
}
}
}
}
The code crashes at the point where I am trying to copy the value of a "title" node that I parse out of my xml file into the list-String-. I am using a list-string- to show that even if you try and copy the value into the array itself (the array that is associated with the adapter), even if you comment out the notifydatasetchanged () line the program still crashes. The xml is well formed and very consistent. I know this because (aecept the fact its really small and I have read it all) ! Why can I not copy every node value into my array/list whilst the loop is in progress?
Any help is massively appreciated. Thank you.
Shorter version:
I cannot write to the List
if(strText.contains(selectedType)){
//
for(int k = 0;k<properties.getLength();k++){
property = properties.item(k);
name = property.getNodeName();
if(name.equalsIgnoreCase("title")){//everytime we hit title grab the value
String strTextsecond = property.getFirstChild().getNodeValue().toString();
ls.add(strTextsecond.toString());
//test = strTextsecond;
}
}
}
Maybe you forget initialize ls? I don't find in your code something like:
ls = new List<String>();

Calling a Method from button click

I'm new to java and I'm trying to run a method once a button is clicked and I am unsure if I'm on the right track. I am selecting 10 questions from a Sqlite database and would like to cycle through each question 0-9 everytime the button is clicked. Once all 10 questions are asked I will move to another activity. I have the app displaying the first question fine but I am having trouble calling the showQuestions method and increasing the questionNum int by one when the button is clicked and passing this onto the method. Any help would be appreciated!
This is the showQuestions method which I am trying to call.
public void showQuestions(Cursor cursor) {
cursor.moveToPosition(questionNum);
while (cursor.moveToNext()) {
// Collect String Values from Query
StringBuilder questiontxt = new StringBuilder("");
StringBuilder answertxt1 = new StringBuilder("");
StringBuilder answertxt2 = new StringBuilder("");
StringBuilder answertxt3 = new StringBuilder("");
StringBuilder answertxt4 = new StringBuilder("");
String question = cursor.getString(2);
String answer = cursor.getString(3);
String option1 = cursor.getString(4);
String option2 = cursor.getString(5);
String option3 = cursor.getString(6);
questiontxt.append(question).append("");
answertxt1.append(answer).append("");
answertxt2.append(option1).append("");
answertxt3.append(option2).append("");
answertxt4.append(option3).append("");
}
}
This is the code for the button which I am working on. There are 4 buttons.
public void onClick(View v) {
switch (v.getId()) {
case R.id.option1_button:
if (questionNum<9) {
questionNum ++;
}
Questions.this.showQuestions(null);
break;
}
And this is the XML code for the buttons.
<Button
android:id="#+id/option1_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/option3_button"/>
OnClick Listener for the button
View option1_button = findViewById(R.id.option1_button);
option1_button.setOnClickListener(this);
Database Query and Allocation to Cursor
//Get the questions and allocate them to the Cursor
public Cursor getQuestions() {
//Select Query
String loadQuestions = "SELECT * FROM questionlist ORDER BY QID LIMIT 10";
SQLiteDatabase db = questions.getReadableDatabase();
Cursor cursor = db.rawQuery(loadQuestions, null);
startManagingCursor(cursor);
return cursor;
}
Thanks in advance.
Questions.this.showQuestions(null);
Why you pass null to the showQuestions method?
Let me guess - it crashes with NullPointerException.
Did you tried
showQuestions(getQuestions())
EDIT:
Some general suggestions:
don't load the question every time when the button is clicked.
make some Question class containing all needed information for a question
when onCreate is invoked, open the database and load all needed questions in some Collection, like ArrayList<Question>
Every time when the user clicks a button, get the next Question element from the Collection and show it

Categories

Resources