Put interface in bundle to start a new activity - android

I need to start an activity from 2 different screens that have two different models but, both models have some shared information which is the one that I need in the new activity. The problem is that I cannot make those models to extend from the same parent, as one of the models already extends one parent. I have thought about creating an interface that contains the shared methods but, if I do that, then how can I put that interface in the bundle required to start the next activity?
I add some simplified code in order to clarify my situation:
public class A extends Model implements CustomInterface {
String name;
String address;
public String getName(){
return name;
}
public String getAddress() {
return address;
}
}
public class B implements CustomInterface {
String name;
public String getName() {
return name;
}
}
public interface CustomInterface {
String getName();
}
My problem is that I need to start an activity with a bundle with the shared information between both models. So, I would like to put CustomInterface in a bundle. How could I do that?
Thanks in advance.

So, I would like to put CustomInterface in a bundle
you could let CustomInterface extend Parcelable. E.g.
public interface CustomInterface extends Parcelable {
String getName();
}
this way the classes implementing CustomInterface will have to implements the method defined in the Parcelable interface. If implemented correctly, you will be able to pass those objects around without problems

Create a singleton class, then you can share data without passing it:
public class MySingleton
{
private static MySingleton instance;
public String customVar;
public static MySingleton getInstance()
{
if (instance == null)
{
// Create the instance
instance = new MySingleton();
}
// Return the instance
return instance;
}
private MySingleton()
{
// Constructor hidden because this is a singleton
}
public void getSomeData()
{
return something;
}
public void getSomeOtherData()
{
return somethingelse;
}
}
Then in your classes:
public class A extends Model {
String name;
String address;
public String getName(){
return name;
}
public String getAddress() {
return address;
}
public String doSomethingWithSharedData(){
MySingleton model = MySingleton.getInstance();
String somedata = model.getSomeData();
}
}
public class B {
String name;
public String getName() {
return name;
}
public String doSomethingDifferentWithSharedData(){
MySingleton model = MySingleton.getInstance();
String somedata = model.getSomeOtherData();
}
}

Related

Error in passing data between activites android while using a custom object

when I pass this object with intent, its not starting the activity.
Custom object code
public class UserVo implements Serializable {
String name,id;
String can_reply,can_view;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public String getCan_reply() {
return can_reply;
}
public void setCan_reply(String can_reply) {
this.can_reply = can_reply;
}
public String getCan_view() {
return can_view;
}
public void setCan_view(String can_view) {
this.can_view = can_view;
}
public void setId(String id) {
this.id = id;
}
Sending data through the intent
intent.putExtra("UserVo",vo);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
Receiving data
intent=getIntent();
UserVo vo= (UserVo) intent.getSerializableExtra("UserVo");
I also tried bundle, but it still does not work.
Look at this link Serializable:
Every serializable class is assigned a version identifier called a serialVersionUID. By default, this identifier is computed by hashing the class declaration and its members. This identifier is included in the serialized form so that version conflicts can be detected during deserialization. If the local serialVersionUID differs from the serialVersionUID in the serialized data, deserialization will fail with an InvalidClassException.
To avoid it:
You can avoid this failure by declaring an explicit serialVersionUID. Declaring an explicit serialVersionUID tells the serialization mechanism that the class is forward and backward compatible with all versions that share that serialVersionUID. Declaring a serialVersionUID looks like this: private static final long serialVersionUID = 0L;
and remember that:
If you declare a serialVersionUID, you should increment it each time your class changes incompatibly with the previous version. Typically this is when you add, change or remove a non-transient field.
For best practise, I recommend you to use Parcelable. It's harder for coding but better for performance.
If for some reason, you can't make your object a Parcelable, try adding a serialVersionUID. You can generate it through your IDE or choose one yourself.
For UserVo you will have
UserVo implements Parcelable {
...
...
public UserVo (){
}
#Override public int describeContents() {
return 0;
}
#Override public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
+ other data ...writInt etc
}
public void readFromParcel(Parcel source){
name = source.readString();
+ other data ..keep the same order
}
public static final Parcelable.Creator<DocumentFile> CREATOR = new Parcelable.Creator<UserVo>() {
#Override
public UserVo createFromParcel(Parcel source) {
return new UserVo(source);
}
#Override
public UserVo[] newArray(int size) {
return new UserVo[size];
}
};
public UserVo(Parcel source )
{
readFromParcel(source);
}
Also have a look at annotations library , it will be easly to send data using #Extra annotation .
In order to send the custom objects from one Activity to Other, you have to serialize the objects with serialVersionID. Try the below modified code for your requirement.
UserVo.java
public class UserVo implements Serializable {
private static final long serialVersionUID = 1L;
String name,id;
String can_reply,can_view;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public String getCan_reply() {
return can_reply;
}
public void setCan_reply(String can_reply) {
this.can_reply = can_reply;
}
public String getCan_view() {
return can_view;
}
public void setCan_view(String can_view) {
this.can_view = can_view;
}
public void setId(String id) {
this.id = id;
}
ActivityA.java - To send the object through Intent
Intent objectIntent = new Intent(ActivityA.this, ActivityB.class);
i.putExtra("sendObjects", UserVo ); //Your object here
startActivity(objectIntent);
ActivityB.java - To Receive the Intent
UserVo mReceiveObjects = (UserVo)getIntent().getExtras().get("sendObjects");

Android passing ArrayList via Bundle [duplicate]

I am trying to pass my own custom object into a bundle:
Bundle b = new Bundle();
STMessage message = (STMessage)a.getAdapter().getItem(position);
b.putObject("message",message);
I get the error:
The method putObject(String, Object) is undefined for the type Bundle
One way is to have your custom object implement the Parcelable interface and use Bundle.putParcelable/Bundle.getParcelable
Model Class
package com.sam.bundleobjectpass;
import java.io.Serializable;
/**
* Created by Samir on 31.8.2016.
*/
public class Model implements Serializable {
private String name;
private String surName;
private int age;
public Model(String name, String surName, int age) {
this.name = name;
this.surName = surName;
this.age = age;
}
public String getName() {
return name;
}
public String getSurName() {
return surName;
}
public int getAge() {
return age;
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Model model = new Model("Sam", "Sami",32);
Intent i = new Intent(MainActivity.this, ReceiverActivity.class);
i.putExtra("Editing", model); // sending our object. In Kotlin is the same
startActivity(i);
}
}
ReceiverActivity
public class ReceiverActivity extends Activity {
TextView txt_name;
TextView txt_surname;
TextView txt_age;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
txt_name = (TextView)findViewById(R.id.txt_name);
txt_surname = (TextView)findViewById(R.id.txt_surname);
txt_age = (TextView)findViewById(R.id.txt_age);
// receiving our object
Model model = (Model) getIntent().getSerializableExtra("Editing");
txt_name.setText(model.getName());
txt_surname.setText(model.getSurName());
txt_age.setText(""+model.getAge());
}
}
// Kotlin
val model: ProgramModel? = intent.getSerializableExtra("Editing") as ProgramModel?
model?.let { // means if not null or empty
txt_act_daily_topic.text = it.title
}
Since using Parsable is designed for high performance IPC transport as mentioned in some of the comments, I tried using a different approach.
My approach uses GSON library by google.
Example
public class Person{
private String name;
private int age;
// Getter and Setters omitted
}
You can have a method in utility class that returns Gson instance, this is for the sake of clean code and organisation. I will use GsonBuilder incase someone what to register custom adapter.
public class Utils {
private static Gson gson;
public static Gson getGsonParser() {
if(null == gson) {
GsonBuilder builder = new GsonBuilder();
gson = builder.create();
}
return gson;
}
}
Moment of truth!
PUT
Bundle args = new Bundle();
String personJsonString = Utils.getGsonParser().toJson(person);
args.putString(PERSON_KEY, personJsonString);
GET
Bundle args = getArguments();
String personJsonString = args.getString(PERSON_KEY);
Person person= Utils.getGsonParser().fromJson(personJsonString, Person.class);
Currently I don't know the performance limitation of this approach. But it works just fine
Make your custom object Parcelable or Serializable then use putParcelable or putSerializable.
Depending on the complexity of your object one or other may be easier.
As Ryan stated. Also if you only want to pass one object on a soft kill consider using onRetainConfigurationInstance and getLastNonConfigurationInstance to pass the serializable object. The entire object tree must be serializable. If you are passing the object via an intent, consider refactoring the object code to a Parceable code later, once the architecture has stabilized. Finally, consider using the fully qualified name of the class when storing the object into the Bundle as in:
inPWState= (PasswordState) getIntent().getSerializableExtra("jalcomputing.confusetext.PasswordState");
Hope that helps.
JAL
It's work
if you make your object class as Serializable
class your_data_class implements Serializable

How to Pass Custom Arraylist content from one Activity to another Activity in android

i have an objects in an custom arraylist as "finaljsoncontent", and now i am trying to pass this "finaljsoncontent" array to another Activity, and i have also tried getters and setters, and also bundle, but i cant, help me how to do this.
Thanks in advance.
Check this out: How do I pass an object from one activity to another on Android?
Your class "JSonKey" should implement parcealable or serializable so that Android can "send" it from an activity to the other activity.
You could try implementing Parcelable, then you can pass it in a bundle. You will need to reduce your object to mostly primitive types to do this. Otherwise you can extend the Application class and store it there. You would retrieve that using the call to getApplicationContext(). Or, of course, you could always create some sort of static globals class that all of your classes can reference.
Here is one of my implementations of parcelable..
package warrior.mail.namespace;
import android.os.Parcel;
import android.os.Parcelable;
public class JView implements Parcelable {
public String subject;
public String from;
public boolean unread;
public String body;
public int inboxIndex;
private long id;
public static final Parcelable.Creator<JView> CREATOR = new Parcelable.Creator<JView>() {
public JView createFromParcel(Parcel in) {
return new JView(in);
}
public JView[] newArray(int size) {
return new JView[size];
}
};
public JView(){
body = "";
}
public JView(String subject,String from,boolean unread){
body = "";
this.subject = subject;
this.from = from;
this.unread = unread;
}
public JView(Parcel parcel){
subject = parcel.readString();
from = parcel.readString();
body = parcel.readString();
unread = parcel.createBooleanArray()[0];
inboxIndex = parcel.readInt();
}
#Override
public int describeContents() {
return inboxIndex;
}
#Override
public void writeToParcel(Parcel out, int arg1) {
out.writeString(subject);
out.writeString(from);
out.writeString(body);
boolean[] array = new boolean[] {unread};
out.writeBooleanArray(array);
out.writeInt(inboxIndex);
}
public void setIndex(int index){
inboxIndex = index;
}
public void setUnread(boolean arg){
unread = arg;
}
public void setContent(String content){
body = content;
}
public void setSubject(String subject){
this.subject = subject;
}
public void setFrom(String f){
from = f;
}
public void setId(long arg){
id = arg;
}
public long getId(){
return id;
}
public void updateIndex(){
}
}
You can either make your class Parcelable(android specific) or make it serializable like in java(just write implements Serializable with your class)

Not Serializable Exception on custom class - Android

So I'm trying to pass an instance of a class I create by intent to a new activity.
public class Room implements Serializable{
/**
*
*/
private static final long serialVersionUID = 6857044522819206055L;
int roomID;
String roomName;
ArrayList<MarkerHolder> markerHolders = new ArrayList<MarkerHolder>();
public int getRoomID() {
return roomID;
}
public void setRoomID(int roomID) {
this.roomID = roomID;
}
public String getRoomName() {
return roomName;
}
public void setRoomName(String roomName) {
this.roomName = roomName;
}
public ArrayList<MarkerHolder> getMarkerHolders() {
return markerHolders;
}
public void setMarkerHolders(ArrayList<MarkerHolder> markerHolders) {
this.markerHolders = markerHolders;
}
}
public class MarkerHolder implements Serializable{
/**
*
*/
private static final long serialVersionUID = -7334724625702415322L;
String marker;
String markerTag;
public String getMarker() {
return marker;
}
public void setMarker(String marker) {
this.marker = marker;
}
public String getMarkerTag() {
return markerTag;
}
public void setMarkerTag(String markerTag) {
this.markerTag = markerTag;
}
}
And I try to pass that class by
Intent svc = new Intent(this, RoomUploader.class);
svc.putExtra("room", room);
try{
startService(svc);
}catch (Exception e){
e.printStackTrace();
}
and I keep getting a Not Serializable Exception which I can't figure out. Both classes implement serializable and have serial Ids. The member variables are just strings, ints, and an array of another class that is also serializable that contains only strings. As far as I know all these things should be serializable, what else could cause this error? Thanks in advance.
Are those classes inner classes of your activity or another class? If so, they have a reference to their outer class (which may or may not be serializable), and you can solve this by making those classes static.
Example:
public static class Room implements Serializable
{
//your implementation
}
public static class MarkerHolder implements Serializable
{
//your implementation
}
Try changing ArrayList to a native array of MarkerHolder:
MarkerHolder[] markerHolders;
Update: My bad. I've always used native array for serialization so not aware ArrayList is indeed serialzable.
Your code looks right. What was the exact error message printed in the logcat (i.e. which class threw the serialization exception)?
Another solution (more work) is to make your objects implement the Parcable interface.
Try to use getApplicationContext() or context instaed of this.

How to declare global variables without using context?

From several classes in my app I want to get String global values without using Context.
If I declare this variables in Application class, SharedPreferences or Strings.xml, then I must use Context for get/set it values.
Using Singleton is not a good practice as I understand from this post.
Is there any good way for using global variables without using context?
Create a global class or store the string in a place that "makes sense". For instance if you have the class Shoes you could do this:
public class Shoes {
public static class BRAND {
public static final String NIKE = "nike";
public static final String REBOK = "rebok";
public static final String ADDIDAS = "addidas";
}
private String brand;
public Shoes() {}
public void setBrand(String brand) {
this.brand = brand;
}
public String getBrand() {
return this.brand;
}
}
Now you can do this:
public static void main(String[] args) {
Shoes myShoes = new Shoes();
myShoes.setBrand(Shoes.BRAND.NIKE);
}
You will find there are many things like this in Android. It would be even better if you used enums instead. Hope this helps.
UPDATE
If you would like to use setters and getters then there are 2 solutions:
The first you would need an instance of the object and since you only want a single instance a singleton design pattern would be required. Really if you synchronize correctly and the design makes sense they can be very good and useful. In your situation I don't think it would be worth the work.
You can take advantage of the static initializer and static methods. You could just remove the final declaration and do what you want with the Strings, like this:
public class Shoes {
public static class BRAND {
public static String NIKE;
public static String REBOK;
public static String ADDIDAS;
static {
NIKE = "nike";
REBOK = "rebok";
ADDIDAS = "addidas";
}
}
private String brand;
public Shoes() {}
public void setBrand(String brand) {
this.brand = brand;
}
public String getBrand() {
return this.brand;
}
}
Or use good encapsulation practices and do this:
public class Shoes {
public static class BRAND {
private static String NIKE;
private static String REBOK;
private static String ADDIDAS;
static {
NIKE = "nike";
REBOK = "rebok";
ADDIDAS = "addidas";
}
public static String getNIKE() {
return NIKE;
}
public static void setNIKE(String name) {
NIKE = name;
}
public static String getREBOK() {
return REBOK;
}
public static void setREBOK(String name) {
REBOK = name;
}
public static String getADDIDAS() {
return ADDIDAS;
}
public static void setADDIDAS(String name) {
ADDIDAS = name;
}
}
private String brand;
public Shoes() {}
public void setBrand(String brand) {
this.brand = brand;
}
public String getBrand() {
return this.brand;
}
}
However I must note: If you are doing this because you cannot get a Context then you are missing something. A context can be obtained from anywhere - objects instantiated by the system are given a context as a parameter. If you have your own custom object you can just pass the ApplicationContext as a parameter or the class using the object itself (this).
Store the values in your strings.xml file. Then call it like this.
String yourString = Context.getResources().getString(R.string.your_string);

Categories

Resources