Concerned about nested classes - android

I am working on a client server application, the server is in Delphi and I am using indy and using packed records for sending/receiving data, on the Android side I was able to find a library named javolution for converting the bytes array to class form so I can easily read the data from received packets or send data.
A normal Packet class looks like this:
class clsCommunicatorPacket extends Struct{
Unsigned16 signature = new Unsigned16();
Unsigned32 version = new Unsigned32();
Unsigned8 dataType = new Unsigned8();
Unsigned16 bufferSize = new Unsigned16();
public boolean isPacked() {
return true; // MyStruct is packed.
}
public ByteOrder byteOrder() {
// TopStruct and its inner structs use hardware byte order.
return ByteOrder.nativeOrder();
}
}
Everything is working as it is supposed to so far and am having no issue, but there will be more than a 100 types of packets and I need to store them in one place so I can access/create it from any activity for sending/receiving.
What I am thinking of doing is create a class file lets say clsAllPackets and then put all the packet classes in that class file.
And when I need to access a specific packet class I can instantiate it like this:
clsCommunicatorPacket Pck = new clsAllPackets().new clsCommunicatorPacket();
So every time I need a class packet I have to instantiate the whole upper class too...
I want to know what will be the consequences of this and how will this effect the performance of the application and what is the best alternative performance wise?

If you make the nested class static, it can be instantiated without having an instance of its outer class. Also, that syntax for instantiating a nested class is incorrect, it should be
new clsAllPackets.clsCommunicatorPacket();

Related

What are the problems in using Intent to pass objects from one activity to another

UPDATE: Please see "accepted" solution below
What I have observed is one way is Intent.
There is no other proper recommended way.
For me serialization is required when you want to transfer data over network/ or when we need to retrieve objects after a while. Only used in some specific scenarios. But here what I saw is to use intent together with serialization to simply share/pass some data.
According to spec, intent will act as the glue between activities.
I would also assume that we can pass instructions /small amount of data to next activity.
My question more specifically is about passing data/big data using intents.
Considering that serialization is required when using intents. Is this a good way?
Note: Please consider that ,won't be able to use Parcelable in this specific scenario, since developing a framework independent of android.
Intents should only pass small packets of data. If you need to pass something big, save it to storage or a database, pass an uri through the Intent and then read the data in the receiving Activity.
Passing big data in the intent will cause drastic problems, up to the point of killing your app process (which is very annoying to the user).
There is a process-scope limit of 1MB of data being passed between components. Please keep in mind that this does not mean that you can pass 1MB of data safely, as there may be multiple Intents being processed at a time.
You could also consider using an event bus library, like greenrobot EventBus, but these require a big amount of discipline, as they basically let you pass everything everywhere.
Intents' extras are indeed the common way. It depends on your data type - primitive types do not require any special work on your size, and custom models should be bundled in a Parcelable object (can't think of why it can't be an option). If you're caching some large data (for example, large pictures), you should consider storing them temporarily on the SD card (as files or in a local SQLite), but this is still your way to go. Try to avoid extra network use and don't cache this data on a remote server.
Another method, especially good for communicating with other types of contexts (services, broadcast receivers) is EventBus.
An approach that I have used is to use a Singleton Holder Class for the Data Object. And access it between components of your process. pseudo code is here below. May have compilation errors. Also mind that you would need a purging mechanism and add a way to keep the data fresh.
class DataSet{
DataSet(String data){
this.data = data;
}
public String data;
}
class Holder{
private Holder(){
}
private static Holder holder = null;
DataSet object = null;
private Holder static getInstance(){
if(null == holder){
holder = new Holder();
}
return holder
}
public void setData(DataSet arg){
object = arg;
}
public DataSet getData(){
return object;
}
}
class Activity A implements View.OnClickListener{
public void onClick(){
Holder.getInstance().setData(new DataSet("this is a big object"));
// At this point the data has been set and has process scope.
startActivity(new Intent(A.this, B.class))
}
}
class Activity B{
DataSet data;
public void onCreate(){
data = Holder.getInstance().getData(); // This point the data is accessible to Class B
}
}

Parceling objects in android to transfer from one activity to another

Recently an interviewer asked me a very tricky question.
There are several parts of the question.
Why (question is why and not how) do you need to parcel objects while sending from one activity to another and not send directly
Answer I gave -
Parcelable gives the capability to developers to restrict object
creation which in a way makes it faster to use.
I was confused on the part, so decided to site difference between using serializable and parcelable :p (clever huuuhhh !),
http://www.developerphil.com/parcelable-vs-serializable/ used this reference.
While using Bundle, when we use String, int we do not need to parcel the data, so do you think the String/int is by default internally parcelled ?
Answer I gave -
because String/int is a primitive data-type, if we had used the
Wrapper class directly, might be possible we had to use parcelable(I
am not sure on that part)
I did not get any useful link after googling, also I or the interviewer is not quite satisfied with the answer.
If you guys can help, would be wonderful !
Why (question is why and not how) do you need to parcel objects while sending from one activity to another and not send directly
Parcelling/serializing objects isn't for speed as you had guessed.
When you're sending data between Activities, and especially between different applications (remember that Intent objects aren't only meant for communication between your own Activities, but are also for between yours and those of other apps as well), you cannot expect the sender and the receiver to have access to the same memory address spaces.
Android's documentation states that applications run in their own discrete memory spaces. Here's a quote to that effect from the docs:
Each process has its own virtual machine (VM), so an app's code runs in isolation from other apps.
So when you want to send an object myObject to some receiving Activity, you can't send its reference/pointer because the receiver won't necessarily have access to the location specified by the pointer. Instead you'll have to send some representation of myObject that the receiver can access and use -- this is why you need to marshall the data into a form that can be unmarshalled, and the easiest way to do so is to simply have the class of the object implement Serializable which lets Java do its best to convert the object into an array of bytes that can be easily sent to and unmarshalled by the receiver. But since Serializable uses reflection, this is slow.
You can use other ways that are faster to marshall the data -- one, for example, is converting the object into its JSON representation using a library like Gson and just sending it across since any JSON document can be represented as a String and easily converted back to a Java Object. Another way, which is probably faster in pretty much all cases is using the Parcelable interface which lets you specify exactly how you want to marshall the data and exactly how it should be unmarshalled. It basically gives you more control on the transmission of the object.
The tl:dr: Parcelling/Serializing etc is used because you can't send memory addresses across, so you have to send the actual data of the object and it has to be represented in some form.
While using Bundle, when we use String, int we do not need to parcel the data, so do you think the String/int is by default internally parcelled ?
How Bundle works internally is that it puts everything into a Map and parcels/unparcels the data as needed (ie when get/put is called). For putting Objects into a Bundle, the object's class needs to implement Serializable or Parcelable because it needs to tell the Bundle how it should be marshalled/unmarshalled internally.
But primitive types and Strings are simple enough and used often enough that the developer doesn't need to specify how that needs to happen and Bundle provides convenience methods for it. I can't give you a solid answer at the lowest level of how they works because a lot of the Parcel code is natively implemented and I couldn't find it online, but they must certainly be straightforward to convert to their representation in bytes.
Just to add what #uj- said, Parcelling/Serializing is needed as #uj- said it will be sent across JVMs so they need to be converted into some format so that the other party will be able to understand.
Let me take an example to explain why serializing/parcelling is needed,
you are sending data from an application written in "C++" to an application written in java, so the following are the classes,
In C++,
class Android {
public: int dataToSend; //for example purpose making field public and omitting setter/getters
}
In Java,
class Android{
public int dataToSend;
}
suppose the C++ code generates dynamic library (which will be generated by compiling using the standard C++ compiler and then linked), and Java code generates a jar (by compiling using the javac).
When the C++ application sends data (object of Android class) to the java application the way it is compiled and linked in C++ is completely different as compared to the way its compiled in java and hence java will be wondering what has this C++ application sent to me.
Hence to get rid of such problems serialisation/parcelling is needed which will make sure that both of the application know how the data is converting while transmitting through network (in case of android how it is transmitted to another activity, may be in same or different application).
And yea when we start comparing Serialisation and Parcelling, Parcelling gets the upper hand as we will be specifying the way the data must be converted when sending the data, else in the case of serialisation the object is converted to string using reflection and reflection always takes time. Hence Parcelling is faster compared to Serialisation.
For your second question,
if we consider the above example itself then we can say that String and int being primitive types (no user defined fields in them) and hence android will be able to handle the marshalling and unmarshalling of the data which will be sent.
I tried going through the code when we go on digging deeper we end up getting native code as said by #uj-.
Some extract from the android source code:
while writing the parcel:
parcel.writeInt(BUNDLE_MAGIC);
int startPos = parcel.dataPosition();
parcel.writeArrayMapInternal(mMap);
int endPos = parcel.dataPosition();
parcel.setDataPosition(lengthPos);
int length = endPos - startPos;
parcel.writeInt(length);
parcel.setDataPosition(endPos);
while reading the parcel,
int magic = parcel.readInt();
if (magic != BUNDLE_MAGIC) {
//noinspection ThrowableInstanceNeverThrown
throw new IllegalStateException("Bad magic number for Bundle: 0x"
+ Integer.toHexString(magic));
}
int offset = parcel.dataPosition();
parcel.setDataPosition(offset + length);
Parcel p = Parcel.obtain();
p.setDataPosition(0);
p.appendFrom(parcel, offset, length);
p.setDataPosition(0);
mParcelledData = p;
set the magic number which will identify the start of the parcel while writing and the same will be used while we read the parcel.
Hope I answered your question.

How to transmit an Android Object over a Socket?

I would like to transmit an Android Object over a Socket with low overhead.
Should I use standard java.io.Serializable or android.os.Parcel?
Thank you!
Neither.
Parcel is designed for IPC, and other uses are albeit arguably efficient, dangerous. The documentation says
Parcel is not a general-purpose serialization mechanism. This class (and the corresponding Parcelable API for placing arbitrary objects into a Parcel) is designed as a high-performance IPC transport. As such, it is not appropriate to place any Parcel data in to persistent storage: changes in the underlying implementation of any of the data in the Parcel can render older data unreadable.
This also means that you need to be sure that the remote side has got the exact same version of Android and of your code to be sure it will work.
Serializable has similar problems, and in the (android) dcumentation there is even a hint towards the solution:
Warning: this interface limits how its implementing classes can change in the future. By implementing Serializable you expose your flexible in-memory implementation details as a rigid binary representation. Simple code changes--like renaming private fields--are not safe when the changed class is serializable.
[...]
Recommended Alternatives: JSON is concise, human-readable and efficient. Android includes both a streaming API and a tree API to read and write JSON. Use a binding library like GSON to read and write Java objects directly.
If you want to move data from one device to another, I think you are better off creating a protocol for the data, ship it over, and populate the remote objects with that data. JSON is probably a good place to start.
Good luck!
If your message is longer, more complex or otherwise you need more efficiency, I would recommend to try use Google Protocol Buffers. They would allow some reasonable amount of alterations like adding new fields, or removing previously optional fields, or adding a completely new structure as a field. However you will also have the real classes with the real setters and getters (can be immutable versions or mutable builders, how do you prefer). Stricter control over that do you put is not as bad thing as may appear.
think XML, but smaller, faster, and simpler
The major drawback of serialized objects is not that you cannot alter the protocol details later. Differently, you can do many compatible changes if you introduce versions numbers and you cannot rename the property name in JSON either if you want legacy client to find that property.
However serialized objects are Java specific and you cannot have a more efficient C++ server client or use Python for prototyping, for instance, if you decide in the future. Protocol buffers are language neutral.
Transmitting an object through a socket depends a lot on what will be receiving the object. Usually such a transfer relies on a text-based serialisation such as XML or JSON.
First, define an object to send. As an example, we can define a class called Message to encapsulate our communications:
public class Message implements Serializable {
private static final long serialVersionUID = 1L; // Your version number
private int senderID;
private String messageText;
public Message(int id, String text) {
senderID = id;
messageText = text;
}
public String getText() {
return messageText;
}
}
Next, instantiate the object, wrap the socket's streams in object streams, then send the message across the socket:
Message sayhey = new Message("123456789", "Hello");
Socket socket = new Socket(host, port);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(sayhey);
On the other side of the socket, the message can be retrieved and used by invoking methods on the returned object:
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
Message messageObject = (Message) in.readObject();
String messageText = messageObject.getText();
you can implement Serializable.

How to structure an app with many activities?

I am making an application presenting a showroom and at this points I have created way too much classes.
The main view is a GridView containing all the series of cars.(Each GridView Item opens a new class, so there are 9 classes with very similar code)
How can I structure it?
To put a bit more flesh on #g00dy, start by creating a class
class BMW {
// Reference codes for every series
public final static int SERIES_1 = 0;
public final static int SERIES_2 = 1;
// etc
public final static int NUMBER_SERIES = 9;
// All the code needed for every car
// eg.
public String giveManufacturuer() {
return "BMW"; // But see #g00dy - use string resources
}
public String giveSeries() {
return XXXXX; // Depends on which approach you choose, see below
}
public String giveModelName() {
return XXXXX; // Depends on which approach you choose, see below
}
}
You can either load all the variations into this class (add in references codes for every car and set up some tables to make indexing easy).
Or you could extend the class using inheritance for each class:
class Series1 extends BMW {
#Override
public String giveSeries {
return "Series 1";
}
}
class Series1M3Door extends Series1 {
#Override
public String giveModelName {
return "3 Door";
}
}
When you then instantiate the final class it will have all three functions working correctly.
This approach is neat, but will still give you a lot of classes. I suspect that for what you are doing, some well thought out information tables (accessed by series and model code) may work better inside a hidden class.
A different, perhaps better approach, might be to structure the code using the information that you are returning as the core classes.
I do not actually have the time to write all this down, mean a unifying class, but here's hint for you. Use a flag, which will indicate the model of the car (Z4,M6 for example), then use it inside the class to determine the tree on which the code should run. Replace the hardcoded values with string resources (just do it, no other remarks are necessary). When instantiating the class and using it's functions, take into account the flag and put it inside an if() condition or inside a switch. If some models require more code than the others, you can always encapsulate it in the part of the code which is responsible for the model. But avoid nesting too much ifs, because it will get messy, like having 100 classes defined which do 99% the same thing as the others. Always try to re-use your code as much as possible. It will reduce the writing (copy/pasting) repetitive stuff, also the size of the application, the memory it will need etc. Conclusion: try combining the common parts of the classes into one class ( to RULE THEM ALL :-) ) and use flags, to let the program knwo what to do there.

Passing data to activity

i'm developing an app that, when i press a button, downloads a XML file, put the xml data in a custom object and passes it to a second activity.
The problem is that something is wrong: when a call the startActivity() function the app crashes with a Runtime error.
My code is:
public void onClickBtn1(View view)
{
final ProgressDialog dlg = ProgressDialog.show( this, "Data wait", "Waiting data from the site ..");
// Thread to wait data
Thread th = new Thread() {
public void run() {
// Download and parse xml data
final DatiSport dati = new DatiSport();
boolean ret = dati.download();
dlg.dismiss();
// check result
if (ret==true)
{
// -- Ok
handlerUI.post( new Runnable() {
public void run() {
Intent intSec = new Intent(AICSActivity.this, SportActivity.class);
intSec.putExtra("datiSport", dati);
startActivity(intSec);
}
});
}
else
{
The app crashes on the startActivity() call. When i break on the startActivity() line i'm not able to look the variable called 'dati' and i guess this is not well defined.
If i substitute dati with 12345, there is not problem.
Which is the problem with dati ?
--- Changed here cause I'm not enabled to reply myself ---
Ok guys. Thanks for replies!
My guess is that i need to re-design the app data.
My first attempt was: download the XML text and accommodate the data into a (rather) complex object. This object contain a list of championships, each of them contains a list of categories, each of them contains a list of teams.
The problem is that, since the Serializable is not working, the implementation of Parcelable is too complex and it should generate almost the same data as the xml file.
I'm wondering if it should be easier passing directly the xml text to other activities (they have to show in turn the list of championships, then the categories of a selected championship, then the list of teams for a selected category...)
Any other idea?
Extract from this Answer :
Serializable is a standard Java interface. You simply mark a class Serializable by implenting the interface, and Java will automatically serialize it in certain situations.
Parcelable is an Android specific interface where you implement the serialization yourself. It was created to be far more efficient that Serializable, and to get around some problems with the default Java serialization scheme.
Extract from this answer :
Seeing Parcelable might have triggered the question, why is Android
not using the built-in Java serialization mechanism? It turns out that
the Android team came to the conclusion that the serialization in Java
is far too slow to satisfy Android’s interprocess-communication
requirements. So the team built the Parcelable solution. The
Parcelable approach requires that you explicitly serialize the members
of your class, but in the end, you get a much faster serialization of
your objects.
After seeing some answer on StackOverFlow, i come to conclusion that Parcelable is optimized than Serialization in android.
How to make class to Parcelable ?? (Check out this, this & this tutorials)
Use a Serializable or Parcelable when passing objects
You need a class to implement the Serializable class
//to pass :
intent.putExtra("MyClass", obj);
// to retrieve object in second Activity
getIntent().getSerializableExtra("MyClass");
Your class would look something like this;
import java.io.Serializable;
#SuppressWarnings("serial") //with this annotation we are going to hide compiler warning
public class MyClass implements Serializable {
public Deneme(Object obj){
this.obj= obj;
}
private Object obj;
}
The Intent class has a method as
putExtra(String name, int value)
thats why it works when you put 12345 at the place of "value", but there is no overloaded version of putExtra that takes "DatiSport" object.
You must ensure that "DatiSport" is Serializable or Parcelable.
See below for more info-
http://developer.android.com/reference/android/content/Intent.html#putExtra%28java.lang.String,%20java.io.Serializable%29
How to send an object from one Android Activity to another using Intents?
How to pass an object from one activity to another on Android
Make your class implement Serializable interface and then pass object instances in intent extra.
To pass data from one Activity to another :
intent.putExtra("ClassName", obj);
To retrieve data in the Second Activity from the First Activity :
getIntent().getSerializableExtra("ClassName");
I found the problem !!!
An internal class were not implementing Serializable!
In the dump window i saw the internal object 'ioe' that said that there was a NotSerializable error and the name of the class!!
Now i checked each internal class and the data is passed to the next activity.
Thanks a lot

Categories

Resources