How to make callbacks in Android. Other than using StartActivityForResult - android

Lets say I have 10 activities in backstack. How can a change in some 10th activity in the backstack(which is an instance of activity A) will trigger a change in 2nd activity in the backstack(which is also an instance of activity A).
The reason I cannot use StartActivityForResult is that the change might occur in the nth activity. I cannot just keep on sending the data backwards using onActivityResult.
Also I cannot use static data because of no.of instances of the same Activity.
Actual Scenario:
Take the case of twitter, where I have my followers list with an option to follow the users in the list and I can select one person, go to his followers list where I will see a follow option for every user and so on.
So, if I follow a user on some 10th list in the backstack, how will that get reflected in the 1st list which contains the same user? I mean it must change from follow to following.

You should be storing your data somehow that is separate from the Activity. Typically this is done in via the sqlite database. The basic idea is when the use performs an action that you wish to record you save it somehow. More than likely in a database. Now that data is stored and accessible.
The next step is how to display updated data in an Activity. This is typically done in Activity#onResume(). In onResume you would perform some actions that can retrieve the stored data and then update your display. startActivityForResult is used more or less for what its name implies. Starting another Activity with the intent of the callee providing the caller some data. It is not used to try to send data and state through the Activity stack.

If you don't want to use startActivityForResult then you need create static instance of each activity to make it accessible from any other activity.eg:-
public class xyz extends Activity
{
private static xyz instance;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
................
................
instance = this;
}
public static xyz getInstance(){
return instance;
}
}

Related

Is there any way to set list item to another activity textview without using PutExtra?

I have one recyclerview so the task is to get the data from another activity and set it to the main activity's recyclerview and when we press on particular row of list so, it get back to the editable mode and edittext fill with old data and replace it with new data and again show update data in recyclerview.
Yes, you can do this by using the startActivityForResult() from list item adapter and at that time you can pass the data through it.
Follow the steps:
1. Implement Main Activities recyclerview
2. Get the data from another activity and show into Main Activities recyclerview.
3. Now, On List item click start the previous activity with startActivityForResult() and pass the full list or the specific list item object as per your list complexity.
4. On The Launched screen get the data from intent and show the filled data to the user.
5. As soon as user makes any change to the data and clicks on submit then finish the activity and you should handle the onActivityResult on the previous screen to update the recycler's view data.
Also, you can store the data in Shared Preferences and while launching the new screen you can get the same data from shared preferences.
There are three major way to communicate component of android we can say pass data, which is bellow
Using BroadcastReceiver: using broadcast receiver you can transfer data between tow activity or activity or service, bellow is the link which will help you
https://developer.android.com/guide/components/broadcasts
Using static variable: You can declare the static variable and set value when you want to use, Like if I am declaring static variable A in Activity1 so I can change or access value of variable A from any of activity using Activity1.A.
Using Intent when starting activity: when we starting activity we can send data using intent put extra.
You can use broadcast, SharedPreferance and Static variables in android.

Can we usually skip using intents by using public variables in Android?

Many times we use intents to send data to a Fragment or get data back from a child. Can't we just put data in a public variable?
For example imagine if we want to get data from user from a dialog box.
I'm just talking about the "possibility". Undoubtedly, It is superior to use intents for code cleanness or safety...
you don't send intent's to fragments, if you want to use objects you need to have your object implement Parcelable then you can just send the object in the intent bundle
public class MyActivity extends Activity {
public int someValue = 1;
}
And in any fragment which has MyActivity as a host you can access ((MyActivity) getActivity()).someValue.
I think what he means is sending (local)broadcast... which is by the way the proper way of doing it according to my understanding.
Of course it is possible to have public (or even protected) fields and access them from a child-fragment with something like this:
assuming your parent activity is named "MainActivity"
((MainActivity) getActivity()).mMyPublicField
or:
((MainActivity) getActivity()).getPublicMethod()
- but I would never recommend doing this!
especially when you also start manipulating the public field you can run into ugly trouble when different threads are in play.
If something needs so be shared across the whole application, use SharedPreferences (if you want to store it for the next app session too) or as I mentioned first LocalBroadCastManager.

Android passing values to activities that have not yet started

I am running into an issue with passing values to activities. I have a Title activity that launches Generating activity. Generating activity launches Play activity. Suppose I want to pass some value such as a boolean to Play activity from Title activity.
Would I have to pass it first to Generating activity and then make Generating activity pass the value to Play? Or can I pass it via putExtra() bypassing Generating activity even if Title activity does not launch Play activity directly?
An intent is a message containing data that will launch an activity. The data is only available to the target activity.
So to answer your questions:
No, you cannot pass intent data from TileActivity to PlayActivity. You must pass it to GeneratingActivity, who in turn would then pass it to PlayActivity.
There are alternatives to using intents such as:
Static/Global data - Use this with care. Because of how Android manages your process, it can be dangerous to use this approach.
SharedPreferences - This is a mechanism for persisting data. Your first activity could save the data in SharedPreferences, and the third activity could read it from SharePreferences. Because of the dangers with approach #1 above, many people take this approach in Android.
You can create a public class with a static variable :
public class Global {
public static boolean play = false;
}
You just need to call Global.play = true in your Title Activity and check the value of Global.play in your Play Activity (or other Activities based on your need)

Passing data through multiple activities in android

I have application in which I have three activities. First and second activity have listview. I need selected values from the first and second activity in order to display some data in the third activity. Which is the best way to do this? Is it better to pass Intent from first to second activity, then from second to third activity or to use SharedPrefenreces?
This depends on what you need. If you need the data to be persistent in the event that your app is destroyed, then you will probably want to save the data in SharedPreferences (will also depend on what type of data since SharedPrefs aren't limited to what they can store) or a DB.
If you aren't worried about it being persistent then passing the data through Intent.putExtra() is fine. You can also create a Bundle and pass the Bundle through the Intent and add the data as you go.
You also have the option of creating a separate class which implements Serializable. Then you can create and pass the class Object through your Intents. Here is a post about doing that
Yes this can be achieved in many ways using:
Intents
Shared Preferences
Sqlite
Sqlite: You can use Sqlite to store data if the data is huge in first and second activity and retrieve the data in the third
activity (But if data is less this is not a feasible solution)
Shared Preferences: Here the data you have saved in the shared-Preferences is done in a xml file, so even if the app is
stopped the data is retained. This is helpful to save the password
and login details etc
Intents: My opinion Passing data with intents is much better option in your case because size of the data passed between your
first, second to third activity is less.
Finalizing :: Just put the data in bundle in first activity. Next get the data(Bundle) in second activity and add the data in second activity in addition to the data in the bundle received from first activity and pass that final bundle from second activity to the third activity.
In my opinion, it would be easiest to create an ArrayManager class, in which your variables are static. This way you can create methods to select and resize your arrays in the ArrayManager class. The only case in which this is bad is if you must hold references to Views, Contexts, or Activities (this will create a memory leak). In that case, codeMagic's solution is ideal.
In your case, if you need to pass same data from first activity to second activity then third activity & your data is small then I suggest use Shared Preferences.
If data passed from first activity to second activity is not same data of second activity to third activity then simply use intent.
There is a tricks. If your second activity always need data from first activity to operate then when you want to go back third activity to second activity then you will get stuck because from third activity you can not get first activity result. In that case saving data i mean Shared Preferences or Sqlite is best.
All above those scenario you need to find your own what is best to use for your app.

Is static variable really safe to exchange data between activities?

I'm working on an application that consist of a couple of activities:
Activity 1: main screen of an application with a "Start" button
Activity 2: user selects its identity from the list (more than one user is going to use the application)
Activity 3: user inputs password
Activity 4: user chooses an event from a timetable (every user has its own timetable with associated events)
Activity 5: user can choose an action connected with an activity.
Activities 6-10: user performs appropriate action.
Below some more information:
every activity from 6-10 have to know what user is logged in and what event has been selected
every activity from 6-10 has a menu that allows the user to go back to activities: 1 (to log out), 4 (to select different event), 5 (to select different action)
Since now, I've been using bundles to exchange data between activities but it seems to complicate the code as the number of actions grow (some actions use a 3-4 activities to collect data from the user). Passing all the data to every created activity doesn't seems to be nice.
I'm thinking about storing the "user name" and selected "event" as a static fields of a class. I will simplify the code very much, but I'm not sure whether this data will persist if the user let say at some point press "home button" and run another application that needs a lot of memory.
Will the data stored in static fields be safe?
It's better to have a custom Application object and store them there. The application object will live aslong as your app does.
http://developer.android.com/reference/android/app/Application.html
You can get access to the Application object by casting getApplicationContext() to whatever your custom Application type is:
public class CustomApplication extends Application {
private String userId;
public void onCreate() {
super.onCreate();
...
}
public String getUserId() {
return userId;
}
...
}
From Activity call: ((CustomApplication) getApplicationContext()).getUserId();
No. You are not guaranteed that these will all exist in the same classloader, in which case you would be dealing with different copies of these classes in different places, and not accessing the same shared state.
It may happen to work now; but no it is not something I would call "safe".
you can use the SharedPreference for this instead of using static variable/object into the class. check out this blog http://android-er.blogspot.com/2011/01/example-of-using-sharedpreferencesedito.html
You should just use the intent system as designed. Statics and Activities can get killed seemingly willy-nilly by Android. Even the Application class can get killed.
Say your have an app consisting of two activities, the first one lets the user store some data in the Application object. The user then clicks a button to start the second activity which displays the data. The user puts their phone down and comes back to it several hours later.
Android might decide to kill the app for various reasons during this time. When the user comes back, picks up the phone and relaunches your app a new Application object will be created and the second activity will be restored but the data the user entered will no longer be available in the Application object because it is a new Application object.
One way to help with this is to use SharedPreferences even for complex objects. Gson is perfectly capable of serializing and deserializing them to SharedPreferences.
To simulate this you can do the following:
$adb shell ps | grep your.app.package
to get the pid of your running app, then
$ adb shell kill -9
then open the app with the task switcher and you will have a new Application object but will be on the second activity.
Static fields work but not graceful. You just need a session object following singleton pattern.
Static data will persist on pressing home button and on opening your application again you will go to the same state where you left but when you run another application which needs lot of memory there are possibilities that you may lost your all static data.
But if you have very less static data then it may persist.
You can also look for SharedPreference.
You can Use the static unless and untill you are sure that this static variable will not conflict the users.
also static variable are class's property so it consumes more memory because lifetime is application level.
other i can suggest is to use shared prefereces which very handy. this shared preferences can be access by any of the activity of your application. so no need to pass bundle and worry about static fields.
last option is which is i dont find importance in your application is "Use Database to store and retreive".
Hope this helps.

Categories

Resources