I am getting a NullPointerException when I am trying to read back a String[] when I create an object from Parcel. Here is my code:
#Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(floors);
out.writeStringArray(indoorMaps);
}
public static final Parcelable.Creator<Building> CREATOR
= new Parcelable.Creator<Building>() {
public Building createFromParcel(Parcel in) {
return new Building(in);
}
public Building[] newArray(int size) {
return new Building[size];
}
};
private Building(Parcel in) {
floors = in.readInt();
in.readStringArray(indoorMaps);
}
So indoorMaps is an attribute of my class, and it a String[], but I get the NullPointerException. I have checked the dev's documentation but there's nothing there.
I followed this tutorial and they are using readStringArray in there.
Any suggestions? Thanks
You are giving Parcel a null array when calling readStringArray. For it to work, you would have to initialize indoorMaps. You probably want createStringArray instead.
Related
Help please, I get the following message, in the following code that I have:
listaFinal = (ArrayList<PuntoNota>) getIntent().getSerializableExtra("miLista");
AdapterDatos adapter = new AdapterDatos(this, listaFinal);
PuntoNota.java
public class PuntoNota implements Serializable{
private String punto;
private String nota;
public PuntoNota (String punto, String nota){
this.punto = punto;
this.nota = nota;
}
public String getPunto(){
return punto;
}
public String getNota(){
return nota;
}
}
AdapterDatos:
public AdapterDatos(Context context, ArrayList<PuntoNota> puntoNotaList) {
this.context = context;
this.puntoNotaList = puntoNotaList;
}
The application is working well, but I get the following message:
Unchecked cast: 'java.io.Serializable' to 'java.util.ArrayList ' less ... (Ctrl + F1).
about this code: (ArrayList ) getIntent (). getSerializableExtra ("myList"); will it be advisable to delete or hide this message?
Root cause: This is a warning from IDE, getSerializableExtra return a Serializable, and you are trying to convert to ArrayList<PuntoNota>. It might throw ClassCastException at runtime if the programe cannot cast it to your expected type.
Solution: In android to pass a user-defined object around, your class should implements Parcelable instead of Serializable interface.
class PuntoNota implements Parcelable {
private String punto;
private String nota;
public PuntoNota(String punto, String nota) {
this.punto = punto;
this.nota = nota;
}
protected PuntoNota(Parcel in) {
punto = in.readString();
nota = in.readString();
}
public String getPunto() {
return punto;
}
public String getNota() {
return nota;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(punto);
dest.writeString(nota);
}
public static final Creator<PuntoNota> CREATOR = new Creator<PuntoNota>() {
#Override
public PuntoNota createFromParcel(Parcel in) {
return new PuntoNota(in);
}
#Override
public PuntoNota[] newArray(int size) {
return new PuntoNota[size];
}
};
}
At sender side
ArrayList<PuntoNota> myList = new ArrayList<>();
// Fill data to myList here
...
Intent intent = new Intent();
intent.putParcelableArrayListExtra("miLista", myList);
At receiver side
ArrayList<? extends PuntoNota> listaFinal = getIntent().getParcelableArrayListExtra("miLista");
You can set a warning Suppression #SuppressWarnings annotation.
Example:
#SuppressWarnings("unchecked")
listaFinal = (ArrayList<PuntoNota>) getIntent().getSerializableExtra("miLista");
It is an annotation to suppress compile warnings about unchecked generic operations (not exceptions), such as casts. It essentially implies that the programmer did not wish to be notified about these which he is already aware of when compiling a particular bit of code.
You can read more on this specific annotation here:
SuppressWarnings
Additionally, Oracle provides some tutorial documentation on the usage of annotations here:
Annotations
As they put it,
"The 'unchecked' warning can occur when interfacing with legacy code written before the advent of generics (discussed in the lesson titled Generics)."
I got an error as below:
Error:(133, 15) error: method setMonkeyBuisness in class QuoteBank cannot be applied to given types;
required: ArrayList<QuoteQuestion>
found: ArrayList<Parcelable>
reason: actual argument ArrayList<Parcelable> cannot be converted to
ArrayList<QuoteQuestion> by method invocation conversion
Both QuoteQuestion and QuoteBank implement Parcelable and all their methods. I cannot type cast parcelable either.
Am I using Parcelable array list correctly?
Here is some part of my code for QuoteBank:
public class QuoteBank implements Parcelable{
public static final String ARRAY_LIST_KEY = "arrayListKey";
private ArrayList<QuoteQuestion> monkeyBuisness;
public QuoteBank(){
}
#Override
public void writeToParcel(Parcel dest, int flags) {
Bundle bundle = new Bundle();
bundle.putParcelableArrayList(ARRAY_LIST_KEY, monkeyBuisness);
dest.writeBundle(bundle);
}
public static final Parcelable.Creator<QuoteBank> CREATOR = new Creator<QuoteBank>() {
#Override
public QuoteBank createFromParcel(Parcel source) {
Bundle bundle = source.readBundle();
QuoteBank qb = new QuoteBank();
qb.setMonkeyBuisness(bundle.getParcelableArrayList(ARRAY_LIST_KEY));
return qb;
}
public void setMonkeyBuisness(ArrayList<QuoteQuestion> monkeyBuisness) {
this.monkeyBuisness = monkeyBuisness;
}
Here is QuoteQuestion code:
public class QuoteQuestion implements Parcelable{
public static final String QUOTE_TYPE = "quoteType";
public static final String QUOTE_NUMBER = "quoteNumber";
public static final String QUOTE_ARRAY = "quoteArray";
public static final String SPEAKER_ARRAY = "speakerArray";
public static final String ANSWER_INDEX_ARRAY = "answerIndexArray";
public static final String ANSWER_CHOICE_ARRAY = "answerChoiceArray";
public static final String CONTEXT_KEY = "contextKey";
public static final String CHOSEN_ANSWER = "chosenAnswer";
public static final String WORD_SPLIT = "wordSplit";
private int quoteNumber;
private String quoteType;
private ArrayList<String> quote;
private ArrayList<String> speaker;
private ArrayList<Integer> answerIndex;
private ArrayList<String> answerChoice;
private String context;
private String chosenAnswer;
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
Bundle bundle = new Bundle();
// insert the key value pairs to the bundle
bundle.putInt(QUOTE_NUMBER, quoteNumber);
bundle.putString(QUOTE_TYPE, quoteType);
bundle.putStringArrayList(QUOTE_ARRAY, quote);
bundle.putStringArrayList(SPEAKER_ARRAY, speaker);
bundle.putIntegerArrayList(ANSWER_INDEX_ARRAY, answerIndex);
bundle.putStringArrayList(ANSWER_CHOICE_ARRAY, answerChoice);
bundle.putString(CONTEXT_KEY, context);
bundle.putString(CHOSEN_ANSWER, chosenAnswer);
bundle.putStringArrayList(WORD_SPLIT, wordSplitTypeA);
// write the key value pairs to the parcel
dest.writeBundle(bundle);
}
public static final Parcelable.Creator<QuoteQuestion> CREATOR = new Creator<QuoteQuestion>() {
#Override
public QuoteQuestion createFromParcel(Parcel source) {
// read the bundle containing key value pairs from the parcel
Bundle bundle = source.readBundle();
QuoteQuestion quoteQuestion = new QuoteQuestion();
quoteQuestion.setQuoteNumber(bundle.getInt(QUOTE_NUMBER));
quoteQuestion.setQuoteType(bundle.getString(QUOTE_TYPE));
quoteQuestion.setQuote(bundle.getStringArrayList(QUOTE_ARRAY));
quoteQuestion.setSpeaker(bundle.getStringArrayList(SPEAKER_ARRAY));
quoteQuestion.setAnswerIndex(bundle.getIntegerArrayList(ANSWER_INDEX_ARRAY));
quoteQuestion.setAnswerChoice(bundle.getStringArrayList(ANSWER_CHOICE_ARRAY));
quoteQuestion.setContext(bundle.getString(CONTEXT_KEY));
quoteQuestion.setChosenAnswer(bundle.getString(CHOSEN_ANSWER));
quoteQuestion.setWordSplitTypeA(bundle.getStringArrayList(WORD_SPLIT));
return quoteQuestion;
}
#Override
public QuoteQuestion[] newArray(int size) {
return new QuoteQuestion[size];
}
};
Also I have a second question while here - It seems all big multi UI apps will have almost all classes implement parcelable? as it is the only way to get data around the app? Is this best practice?
Split your statement into two, using a variable to hold the properly-typed ArrayList, like this:
ArrayList<QuoteQuestion> qq = bundle.getParcelableArrayList(ARRAY_LIST_KEY);
qb.setMonkeyBuisness(qq);
Why this works, whereas casting does not? I have no idea. If anyone knows, please replace this paragraph!
As for the second question, about implementing Parcelable all over the place: The temporary-by-design nature of all Activities and heavy usage of Intents can lead to requiring Parcelable in many places. Certain app design patterns can help mitigate the problem. For example, following MVC techniques, your application data can live within the Model, accessible via a custom class derived from Application. This allows most Activities to avoid saving & restoring bundled data, as they are simply Views of the Model, which persists across device rotations etc. This is a much bigger topic of course, with many different approaches, but hopefully this sparks some ideas.
It should suffice to write:
qb.setMonkeyBuisness(bundle.<QuoteQuestion>getParcelableArrayList(ARRAY_LIST_KEY));
I'm attempting to transfer one object containing an ArrayList of other Objects to another Activity in Android. The idea is to add those to an ArrayList and display them so that the Task in question can be performed.
Task ta = new Task(n, o, t, v, subList);
Intent i = new Intent(this, ActivityList.class);
i.putExtra("task", ta);
startActivity(i);
This is the intent. Task is Parcelable, and the subList is an ArrayList of class Subtask which is also Parcelable.
Surely, since ArrayList always implement Serializable, Parcelling them shouldn't be a problem? The constructor arguments are: String, byte, byte, byte, ArrayList. The bytes are to be used as booleans.
Here is the Parcel code for Task if you need it:
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(taskName);
dest.writeByte((byte) (soundCueOne ? 1 : 0));
dest.writeByte((byte) (soundCueTwo ? 1 : 0));
dest.writeByte((byte) (vibrCue ? 1 : 0));
dest.writeSerializable(myList);
}
private Task(Parcel in) {
this.taskName = in.readString();
this.soundCueOne = in.readByte() != 0;
this.soundCueTwo = in.readByte() != 0;
this.vibrCue = in.readByte() != 0;
this.myList = (ArrayList<Subtask>) in.readSerializable();
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public Task createFromParcel(Parcel in) {
return new Task(in);
}
public Task[] newArray(int size) {
return new Task[size];
}
};
Can anyone see what is wrong with the code? It's obviously somewhere, maybe even in the Subtask class, since the emulator crashes as soon as the Task is constructed and it tries to Parcel it.
If I see correctly, then the problem is that you are trying to use the ArrayList<T> as a Serializable, even though it is not a Serializable - it is a Parcelable.
Therefore, replace
dest.writeSerializable(myList);
with
dest.writeTypedList(myList);
and replace
this.myList = (ArrayList<Subtask>) in.readSerializable();
with
this.myList = in.readTypedList(new ArrayList<Subtask>(), Subtask.CREATOR);
So i have native function in C declared as int NgSetEvent (int event, long callback). long Callback represent the callback function pointer. Callback prototype is declared as int oncodeline(int code, int documentid, char *string). The callback should be registered with method NgSetEvent. The problem is how to get pointer to that function which should be long or Nativelong? I have tried a lot of different aproaches but none of them gave a result. Callback was never invoked.
I have tried to do like it says in Turn a Callback into a Pointer in JNA, but with no success. i don't know what to try anymore.
Any help will be appreciated.
OnCodeline
public interface OnCodeline extends Callback {
int oncodeline (int code, int documentid, byte[] string);
}
OnCodelineStruct
public class OnCodelineStruct extends Structure {
public OnCodeline onc;
#Override
protected List getFieldOrder() {
return Arrays.asList(new String[] { "onc" });
}
}
Main class
OnCodelineStruct onCodelinStruct;
onCodelinStruct = new OnCodelineStruct();
onCodelinStruct.onc = new OnCodeline() {
#Override
public int oncodeline(int code, int documentid, byte[] string) {
System.out.println("This IS a CALLBACK!");
return 0;
}
};
sbDll.NgSetEvent(0, onCodelinStruct.getPointer().getNativeLong(0));
I'll get right to it.
So I have code that gets a Null Pointer Exception. I've tried looking up what causes it and how to fix it, but that's why I'm confused with this particular code. It was working just fine earlier today and now its throwing the exception. Any help? I'm probably just overlooking something silly but it's quite frustrating. Code follows:
import java.util.*;
import java.io.*;
public class ShopMain<T> {
List<T> stock;
public void Shop() { stock = new LinkedList<T>(); }
public T buy() { return stock.remove(0); }
void sell(T item) { stock.add(item); }
void buy(int n, Collection<? super T>items) {
for (T e : stock.subList(0, n)) {
items.add(e);
}
for (int i=0; i<n; ++i) stock.remove(0);
}
void sell(Collection<? extends T> items) {
for (T e : items) {
stock.add(e);
}
}
public static void main (String[] args) {
ShopMain<Marker> paintballShop = new ShopMain<Marker>();
Console console = System.console();
System.out.println("1 - Test Suite");
String input = console.readLine("Please select the corresponding number to your choice.\n");
if(input.equals("1")){
Stack<Marker> stack = new Stack<Marker>();
Set<Marker> hashset = new HashSet<Marker>();
System.out.println("Test Suite : Tests List, Stack, HashSet");
paintballShop.sell(new Geo3());
paintballShop.sell(new Ego11());
paintballShop.buy();
paintballShop.buy(2, stack); //Stack use
paintballShop.sell(stack); //Stack use
paintballShop.buy(3, hashset); //HashSet
paintballShop.sell(hashset); //HashSet
System.out.println("Tests Complete");
}
}
}
Exception error occurring at runtime:
Exception in thread "main" java.lang.NullPointerException
at ShopMain.sell(ShopMain.java:14)
at ShopMain.main(ShopMain.java:39)
These last bits are just class 'placeholders' for the objects and their parent class.
public class Marker{}
public class Geo3 extends Marker{}
public class Ego11 extends Marker{}
Thanks again for any help.
That's because your List List<T> stock; is still uninitialized. You need to initialize it for you to be able to add, remove elements to/from it. By default, its null and thus, when you try to call a method on it, you get the NullPointerException.
This happens because you don't have a constructor at all. Shop() is not the constructor of your class. A constructor has the same name as the class, and thus you need to have your constructor like this
public ShopMain() { stock = new LinkedList<T>(); }
Incase, Shop() is a valid method, then you need to call this method so that your list is initialized and only then call the other methods.
paintballShop.Shop(); // Call this method to init your list.
change to constructor..
public ShopMain() { stock = new LinkedList<T>(); }
You probably need to change:
public void Shop() { stock = new LinkedList<T>(); }
//doesn't look a method name, may be this is what you missed
to
public ShopMain() { stock = new LinkedList<T>(); }
You don't have a constructor for ShopMain that initializes your List.
Add this:
ShopMain() {
stock<T> = new ArrayList<T>();
}
Basically it comes do to the fact that stock is never initialised. I imagine that the class use to be called Shop
You could change...
public class ShopMain<T> {
List<T> stock;
public void Shop() {
stock = new LinkedList<T>();
}
To...
public class ShopMain<T> {
List<T> stock;
public ShopMain() {
stock = new LinkedList<T>();
}
Which will initialise the List when the class is constructored...