What is the parameter for Parcel.readStringArray()? - android

I am trying to save the state in my Fragment through the use of Parcelable.
This lead to the following code when I wish to get back the a String array that I saved in the Parcelable:
public MyObject createFromParcel(Parcel in) {
titles=in.readStringArray(???);
}
Now readStringArray needs a parameter, a String[]... But why? It could just give the Strings that I stored in it. I don't know a priori how many there were, so this sucks. :(
The documentation says the following:
That is, nothing.
EDIT: If anyone has the same problem: I ended up using writeBundle()/readBundle() and putting my String[] into the Bundle.

Use createStringArray() instead of readStringArray(String[]). It will return the array you need.

Here is an implementation of this method from Android 4.1.2:
public final void readStringArray(String[] val) {
int N = readInt();
if (N == val.length) {
for (int i=0; i<N; i++) {
val[i] = readString();
}
} else {
throw new RuntimeException("bad array lengths");
}
}
So it writes values to given array. And returns nothing.

I think it might be useful to view these two methods, readStringArray(String[] val) and createStringArray() side by side:
Let's look at readStringArray(String[] val) method first. It requires a String[] as a parameter and might result in a NullPointerException if you pass a non-initialised array object (null). Also, you'll have to know exactly the length of the array (N), otherwise you'll get the RuntimeException thrown from the method:
public final void readStringArray(String[] val) {
int N = readInt();
if (N == val.length) {
for (int i=0; i<N; i++) {
val[i] = readString();
}
} else {
throw new RuntimeException("bad array lengths");
}
}
Oh the other hand, with createStringArray() you don't need to form and provide a String[] as a parameter, it will be formed for you by the method with the correct length too, so you don't have to worry about either NullPointerException or RuntimeException:
public final String[] createStringArray() {
int N = readInt();
if (N >= 0) {
String[] val = new String[N];
for (int i=0; i<N; i++) {
val[i] = readString();
}
return val;
} else {
return null;
}
}
All in all, as a result of this basic analysis we can jump to conclusions and say that the second method is better and safer..

Related

Should I avoid foreach for ArrayList in Andorid 4.0+?

I just read this from the book "Android Programming - Pushing the Limits" by Hellman, Erik. Page 38:
void loopOne(String[] names) {
int size = names.length;
for (int i = 0; i < size; i++) {
printName(names[i]);
}
}
void loopTwo(String[] names) {
for (String name : names) {
printName(name);
}
}
void loopThree(Collection<String> names) {
for (String name : names) {
printName(name);
}
}
void loopFour(Collection<String> names) {
Iterator<String> iterator = names.iterator();
while (iterator.hasNext()) {
printName(iterator.next());
}
}
// Avoid using enhanced for-loops for ArrayList
void loopFive(ArrayList<String> names) {
int size = names.size();
for (int i = 0; i < size; i++) {
printName(names.get(i));
}
}
These methods show four different ways of looping through collections
and arrays. The first two methods have the same performance, so it’s
safe to use the enhanced for-loop on arrays if you’re just going to
read the entries. For Collection objects, you get the same
performance when using the enhanced for-loop as when you manually
retrieve an Iterator for traversal. The only time you should do a
manual for-loop is when you have an ArrayList object.
I searched before, the foreach and the normal for loop have no performance difference in Java, is there any special reason only for Android (version 4 +)?
Please check info about for loops here

Java, what is best way to compare two lists?

I have two lists of Default and Chrome browsers history.
I want to merge these two lists into one list.
I need to update item if I find it duplicate (is common between two lists).
So, my "BrowserRecord" class is like this:
public class BrowserRecord {
private long id;
private int bookmark;
private long created;
private long date;
private String title;
private String url;
private long visits;
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BrowserRecord record = (BrowserRecord) o;
return url.equals(record.url);
}
#Override
public int hashCode() {
return url.hashCode();
}
// other getter setter methods
...
}
and finally, I have a method that gets browsers histories and does merging:
public List<BrowserRecord> getHistory() {
List<BrowserRecord> browserList = new ArrayList<BrowserRecord>();
// get history of default and chrome browsers
List<BrowserRecord> defaultList = getDefaultBrowserHistory();
List<BrowserRecord> chromeList = getChromeBrowserHistory();
Log.e(TAG, "=> size of Default browser:" + defaultList.size());
Log.e(TAG, "=> size of Chrome browser:" + chromeList.size());
// compare list A with B, update A item if equal item found in B and push it to tempList
for(int i=0; i<chromeList.size(); i++) {
BrowserRecord chromeBrowser = chromeList.get(i);
for(int j=0; j<defaultList.size(); j++) {
BrowserRecord defaultBrowser = defaultList.get(j);
if(chromeBrowser.equals(defaultBrowser)) {
if(chromeBrowser.getBookmark() != defaultBrowser.getBookmark())
chromeBrowser.setBookmark(1);
chromeBrowser.setVisits(chromeBrowser.getVisits() + defaultBrowser.getVisits());
}
}
browserList.add(chromeBrowser);
}
// compare list B with A, jump if equal item found in A, push to tempList if item not found
for(int i=0; i<defaultList.size(); i++) {
BrowserRecord defaultBrowser = defaultList.get(i);
boolean found = false;
for(int j=0; j<chromeList.size(); j++) {
BrowserRecord chromeBrowser = chromeList.get(j);
if(defaultBrowser.equals(chromeBrowser)) {
found = true;
break;
}
}
if(!found)
browserList.add(defaultBrowser);
}
Log.e(TAG, "=> size of final browser:" + browserList.size());
return browserList;
}
I have tested this method and is working fine. Since my history records on mobile device after 3 years didn't exceed more than 200 records on one list and 150 for others, I assume something similar is happening for other users. But I'm sure is not optimum way.
What do you recommend?
any suggestion would be appreciated. Thanks.
Not sure I understand correctly, but it seems like what you're trying to do is, given both lists, create a final list which will contain all of the elements from both lists, removing any duplicates.
If this is the case, then take a look at Java's TreeSet class. If you iterate over all of the elements from both your lists and insert them into a TreeSet, you will basically get the result you're looking for. You can then use an Iterator to create an ArrayList containing all of the non-duplicate items from both your lists. As a side-effect of using a TreeSet, they will ordered (you can also use either a HashSet if you don't care about the order or a LinkedHashSet if you want to preserve the order of insertion).

string index out of bound exception while carrying search operation

when I am carrying out a search operation after fetching the contacts,it shows this exception when I type the letters very fast in the search bar and the application crashes.Could you please help me out to resolve this issue.I am including the portion of the code also along
#Override
public boolean onQueryTextChange(String newtext) {
String searchString = newtext;
int textLength = searchString.length();
ArrayList<Masterlistmodel> type_name_filter = new ArrayList<Masterlistmodel>();
/* String text = edtField.getText().toString(); */
for (int i = 0; i <masterarr.size(); i++) {
String Name = masterarr.get(i).getName();
if (searchString.equalsIgnoreCase(Name.substring(0,
textLength))) {
type_name_filter.add(masterarr.get(i));
}
}
type_name_copy = type_name_filter;
listUpdate(type_name_copy);
return true;
}
#Override
public boolean onQueryTextSubmit(String arg0) {
// TODO Auto-generated method stub
return false;
}
First thing I'd point out is that we don't know what kind of object is masterarr, So I'll guess is like an ArrayList.
I'd try not to use the .size() but the .length() method, size is related to capacity and length is related to the amount of items actually in the array.
Also, as #rsinha said, I think a possible mistake is when you try to execute the equalsIgnoreCase method and the Name variable in that iteration has a lenght shorter than the lenght of the String typed by the user, so I would try:
for (int i = 0; i <masterarr.size(); i++) {
String Name = masterarr.get(i).getName();
if (searchString.equalsIgnoreCase(Name.substring(0,
Math.min(textLength,Name.length())))) {
type_name_filter.add(masterarr.get(i));
}
}
Try first using .length() and if does not work, try the changes in the for loop. I see no more in your code I could help with.
You get IndexOutOfBoundsException when you want to access an array index which is out of range. For example:
String[] myArray = new String[10];
myArray[10] = "test"; // 10 is out of limits(0-9)
Would produce such an exception.
with this:
ArrayList<String> result= new ArrayList<String>();
Then you can add elements to this list with the following:
// result[i] = trax.substring(s1+4,s2);
result.add(trax.substring(s1+4,s2));
It will work for you and it will remove this exception.
'textLength' is length of the search string entered by user. An entry of this length may not be in your master list 'masterarr'. You may try:
String Name = masterarr.get(i).getName();
if (Name.startsWith(searchString)) {
type_name_filter.add(masterarr.get(i));
}
Add the first statement in the method "onQueryTextChange"
if(newtext==null) return true;
Then try

Converting String array to Integer Array

Since I couldn't figure out an easy way to convert my string array into an integer array, I looked up an example for a method and here is what I ended up with:
private int[] convert(String string) {
int number[] = new int[string.length()];
for (int i = 0; i < string.length(); i++) {
number[i] = Integer.parseInt(string[i]); // error here
}
return number;
}
parseInt requires a string which is what string[i] is but the error tells me "The type of the expression must be an array type but it resolved to String"
I can't figure out what is the problem with my code.
EDIT: I'm an idiot. Thanks all it was obvious.
You're trying to read a string as if it were an array. I assume you're trying to go through the string one character at a time. To do that, use .charAt()
private int[] convert(String string) {
int number[] = new int[string.length()];
for (int i = 0; i < string.length(); i++) {
number[i] = Integer.parseInt(string.charAt(i)); //Note charAt
}
return number;
}
If you expect the string to be an array of strings, however, you left out the array identifier in the function prototype. Use the following corrected version:
private int[] convert(String[] string) { //Note the [] after the String.
int number[] = new int[string.length()];
for (int i = 0; i < string.length(); i++) {
number[i] = Integer.parseInt(string[i]);
}
return number;
}
You have an error in your code. Use this code:
private int[] convert(String[] string) {
int number[] = new int[string.length];
for (int i = 0; i < string.length; i++) {
number[i] = Integer.parseInt(string[i]); // error here
}
return number;
}
Your method's parameter is a String and not a String array. You cannot access elements in a String with string[i]. If you want to actually get a single character from a String, use 'String.charAt(..)' or 'String.substring(..)'. Note that charAt(..) will return a char but those are easy enough to convert to Strings.
Use Arrays.asList( YourIntArray ) to create arraylist
Integer[] intArray = {5, 10, 15}; // cannot use int[] here
List<Integer> intList = Arrays.asList(intArray);
Alternatively, to decouple the two data structures:
List<Integer> intList = new ArrayList<Integer>(intArray.length);
for (int i=0; i<intArray.length; i++)
{
intList.add(intArray[i]);
}
Or even more:
List<Integer> intList = new ArrayList<Integer>(Arrays.asList(intArray));
.#this is worked for me

Why isn't there a remove(int position) method in Android's JSONArray?

I started building an Android app that uses a flat file for storage. The app doesn't store more than six records, and I'm familiar with JSON, so I just write out a JSONArray to the file.
I just discovered today, though, that the Android JSON API doesn't include a remove() option. Huh? Do I have to dump the array into another collection, remove it, then rebuild the JSONArray? What's the point?
This is useful sometimes in android when you want to use the json structure directly, without looping around to convert. Please use this only when you do things like removing a row on long clicks or something like that. Don't use that inside a loop!
Notice that I only use this when I'm handling JSONObject inside the array.
public static JSONArray remove(final int idx, final JSONArray from) {
final List<JSONObject> objs = asList(from);
objs.remove(idx);
final JSONArray ja = new JSONArray();
for (final JSONObject obj : objs) {
ja.put(obj);
}
return ja;
}
public static List<JSONObject> asList(final JSONArray ja) {
final int len = ja.length();
final ArrayList<JSONObject> result = new ArrayList<JSONObject>(len);
for (int i = 0; i < len; i++) {
final JSONObject obj = ja.optJSONObject(i);
if (obj != null) {
result.add(obj);
}
}
return result;
}
I use:
public static JSONArray removeFrom(JSONArray jsonArray, int pos){
JSONArray result = new JSONArray();
try {
for (int i = 0; i < jsonArray.length(); i++) {
if (i != pos) {
jsonArray.put(jsonArray.get(i));
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
The point is that JSONArray and JSONObject are meant to (de)serialize data to JSON, not manipulate data. A remove() method may seem to make sense, but where's the limit? Would you expect to be able to access attributes on serialized objects? Access or update nested data structures?
The idea is, indeed, that you manipulate data structures "natively".
You might want to check it out now. Seems like API 19 from Android (4.4) actually allows this method.
Call requires API level 19 (current min is 16): org.json.JSONArray#remove
I got that error while trying to use it. Hope it helps you, now that it's there!

Categories

Resources