Passing Data from multiple Activities to a single activity - android

Hello Everybody,
&nbsp&nbsp&nbsp&nbspI have an app that a couple of classmates and I did for a class project. We are now continuing the app to improve and streamline it. Here is what I have so far:
SplashScreen
HomePage
Hole 1 - 18
ScorePage
AboutPage
Home Screen Hole 1 - 18 Score Page About Page
I have pretty much got it all figured out except for a few small things. The issue that I am working on right now though is:
Passing data from each Hole Page to the Score Page.
I know how to pass it from page to page and I could brute force it, because that is how I initially had it, but it looks sloppy and I would like to not do that if possible.
//Code (partial)
//(From Hole 1)
#Override
public void onClick(View v)
{
TextView tvScoreLbl = (TextView) findViewById(R.id.scoreLbl);
tvScoreLbl.setText(String.valueOf(count));
if(v == findViewById(R.id.btnAdd))
{
count++;
tvScoreLbl.setText(String.valueOf(count));
}
else if(v == findViewById(R.id.btnMinus))
{
count--;
tvScoreLbl.setText(String.valueOf(count));
}
else if(v == findViewById(R.id.btnPrev))
{
Intent i_prev = new Intent(Hole_01.this, HomePage.class);
startActivity(i_prev);
}
else if(v == findViewById(R.id.btnNext))
{
Intent i_pass = new Intent(Hole_01.this, ScorePage.class);
i_pass.putExtra("score1", tvScoreLbl.getText().toString());
Intent i_next = new Intent(Hole_01.this, Hole_02.class);
startActivity(i_next);
}
//(From ScorePage)
String score;
TextView tvScore1 = (TextView) findViewById(R.id.tvScore1);
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.scorepage);
Button btnHome = (Button) findViewById(R.id.btnHome);
btnHome.setOnClickListener(this);
score = getIntent().getExtras().getString("score1");
tvScore1.setText(score);
}
Thanks in advance.

The best answer depends on how long you need your data to persist.
If you need it to persist across a long period of time (days/weeks) then store the data to the internal or external storage using either SQLite or creating a custom object that represents all the data from the 'hole page' and serialize that object and write it to disk.
If you don't need the data to persist then I'd do as you currently are and continue passing the data as you are, from Activity to Activity. It may seem 'sloppy' to you but it is how you are supposed to pass data between Activities.
Perhaps creating an object for the data you want to pass and have it implement the Parcelable interface would make it less 'sloppy' in your eyes. Here's a link to a tutorial for Parcelable objects.
Another option is to use the global Application context as suggested already BUT be warned it comes with a big problem - if the app is killed in the background any data stored in the Application class is lost, so you'll have to account for that happening.
A DB is excessive if you're only storing a tiny bit of info, the Application context will lose data if the app is killed by the OS.
So if you want to persist data for a period of time, use serialization to write the object ( if it's just the score then a simple File IO stuff would do the job with no need for serialization). Or if you only need it to persist while the app is running (foreground or background) then pass the data between Activities.

Rather than passing data between all your Intents with putExtra why not use a little SQLite DB to store the result of each activity that the score screen could read.
SQLite Docs
Android Notepad Tutorial is good for SQLite example as well

Hold all the state in an Application Class.
Write to it as needed, from whatever Activity.
Read from it in the ScorePage Activity.
More details and example available here: (Using the Android Application class to persist data)

Related

Fill ListView With Items From Previous Activity

I'm new to Android programming, and still teaching myself to code.
Currently I'm teaching myself about GridViews and still coding that project with tutorials so I have nothing to show right now, but the basic idea is the following...
If I have images of groceries in GridView in the first activity and when you click an image you will be able to open a new activity with a larger image and you could input the number how many you things you need, like 5 apples or whatever.
All of that is more or less clear to me how to do.
But how would I send the number and image to a new (third) activity with a ListView that would list all the items you need to buy at the grocery store? How would I be able to fill the list only with items after you enter the number on the previous activity with the large picture and click an "OK" or "Add" button or whatever and not list absolutely everything?
Thanks!
It's difficult at first, but you can use an SQLiteDatabase to store the data.
It's not a quick solution for you, but definitely worth learning about if you're serious to learn android. Here's a link to the official stuff:
https://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
I personally used this tutorial:
http://www.androidwarriors.com/2016/02/android-sqlite-database-tutorial-sqlite.html?m=1
Sharing some data between multiple activities or fragments is a very common situation. One way around it is implementing a Singleton Pattern.
In your case you can design some kind of data structure for your purpose and manage it inside shared singleton class. For example something like this:
public class ShoppingListManager {
private static ShoppingListManager instance = new ShoppingListManager();
private List<ShoppingItem> shoppingList;
public static ShoppingListManager getInstance() {
return instance;
}
public List<ShoppingItem> getShoppingList() {
return shoppingList;
}
public void addShoppingItem(ShoppingItem item) {
this.shoppingList.add(item);
}
...
// Make the constructor private so that this class cannot be instantiated
private ShoppingListManager(){
shoppingList = new ArrayList<String>();
}
}
Then you can access your data anywhere in your code and manage shared data in any way you'd like.
ShoppingListManager.getInstance().getShoppingList();
// You can add items in any activity
ShoppingListManager.getInstance().addShoppingItem(item);
One point to remember never store context in singleton classes as it will lead to memory leaks.

Flux: Detail Page/Single Item Store

I'm an early and very happy adopter of both Flux and React so much so that, recently, I ported Fluxxor into Android and it's been okay so far.
The issue I am having with it Flux is dealing with data for a Single Item or Details Page. Bear with me below. I will try to be as clear as I can.
The pattern I am using is.
On page load(componentWillMount/componentWillReceiveProps and onStart), I check if the id passed to the page (via url or bundle) matches the id of the item currently in the store and the page if the store is in a processing or success state.
If yes, I do nothing, else, I dispatch an action to load the data for that item.
componentWillMount: function () {
id = this.props.params.path.split("-")[0];
var artistData = this.props.state.artistData;
if(artistData.id != id)
this.getFlux().actions.artistActions.loadArtist(id);
else if (!artistData.artist && !artistData.loading)
this.getFlux().actions.artistActions.loadArtist(id);
this.getFlux().actions.userActions.fetchSuggestions();
}
protected void onStart() {
GenreSongsStore.State state = App.getFlux().getStore(GenreSongsStore.class).getState();
if(mId == state.Genre.getId()) {
if (state.HasMore)
App.getFlux().getActions().Genres.songs(mId, state.Page + 1);
}
else
App.getFlux().getActions().Genres.songs(mId, 1);
super.onStart();
}
In React this is fine since you use a single state on the root. I didn't bother too much until I started working with Android.
Here, I don't use a single state but query the relevant store and it totally smells
If you are not using that page, the data is still held in memory
Since the data is not shared it seems there is no benefit to doing it like this
Won't it simply be easier to load the data in the component/activity/fragment?
However, I get the benefit of maintaining the currently loading state. So the user can minimize and reopen the app and we continue (no need for saving an instance bundle).
I know by doing it like this, I lose the benefit of unidirectional data flow. But it seems to make more sense in the context of Android (pun intended).
Can I have your views on how you do this and if I'm simply worried about nothing.
NB: The data is not shared by any other stores at.

Collect device data on android regularly

I managed to create an application that collects basic info from the device like android version,CPU,total RAM,free RAM,etc. Some of the data i need to collect is dynamic so i want my application to collect that data every minute.I also want my application to do so in the background. Here is how my code is setup:
public class Sniffer extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sniffer);
model_device=(TextView) findViewById(R.id.model1);
versiune_android=(TextView) findViewById(R.id.versiune1);
total_RAM=(TextView) findViewById(R.id.total_RAM1);
free_RAM=(TextView) findViewById(R.id.free_RAM1);
total_disk=(TextView) findViewById(R.id.total_disk1);
free_disk=(TextView) findViewById(R.id.free_disk1);
CPU=(TextView) findViewById(R.id.CPU1);
nivel_baterie=(TextView) findViewById(R.id.baterie1);
//get the requested data and set the corresponding text
getDeviceData();
}
Inside getDeviceData i read the /proc files and whatnot to obtain everything. Can i create a service that can run in the background and every x minutes update the data by calling getDeviceData again ? Let's take this scenario : start my app,check the data, leave app on, go check my email, listen to a song on youtube then i come back to my app (without closing it)and the collected data should have changed. How would i go about doing so using a service, i think this is the best solution. I need just a bump in the right direction, maybe a skeleton code on where my stuff should go. Thanks

Pulling data from one Tab Activity to another

Everything I've read about Intents talks about using them to push data, or to start one Activity from another Activity. I want to pull data from an Activity that's already running.
The Tab Layout tutorial at http://developer.android.com/resources/tutorials/views/hello-tabwidget.html illustrates what I want to do. (My app is doing some engineering calculations instead, but the tutorial code provides a good analogy to my app.) The tutorial creates an app with three tabs, and each tab hosts a separate activity.
To expand on the example in the tutorial, suppose I select an artist in the Artists tab/activity. I want to be able to select the Albums tab/activity and have it display all the albums featuring that artist.
It seems to me that I need to use an Intent to do this. All of the tutorials I've found assume that I would create a "See albums" Button in the Artists tab/activity, and that pressing the Button would execute an Intent that starts the Albums activity and passes artistName.
I DO NOT want to create that Button. Real estate on the Artists layout is precious, and I have a perfectly good Albums tab, AND the HelloTabWidget activity already contains an intent to create the Albums tab.
Besides, a user will want to skip back and forth between Album and Artist in order to change artist selections, and the tabs are a perfectly good way to do this. There's no need to complicate the UI with another button.
So how can I have the Albums activity PULL artistName from the Artists activity when the Albums tab is selected (or the Albums layout is displayed), rather than have the Artists activity START Albums and PUSH the artistName?
Equivalents I can think of from other programming worlds:
Global variables. Discouraged in Android devt, right? And if they do exist, what are they called?
A getter, like artistName = Artists.getArtistName(); . I get the feeling that it's not that easy.
Writing to, and reading from, a file - that is, mass storage or non-volatile memory. I don't need the artistName value to be permanent. It will be reset to null every time the user launches the application.
So how is it done in the Android world? Do I use an Intent - and if so, how?
Global variables were the right answer.
I thought Java discouraged their use, but a couple of links that appeared in the "Related" links on the right margin of this window mentioned them directly. One was "Android: How to declare global variables?" and the other was "how to pass value betweeen two tab in android". Both pointed to the Application Class as the place to define global variables and methods. Armed with this new knowledge, I found an article called "Android Application Class" on the Xoriant blog that expanded on the StackOverflow answers.
It's best to review those three links first. I need to add some tips to what those authors have said.
Your Application class has to be in its own separate file. (That might be a "duh" to some people, but not to everybody.) Here's a good framework for an example called Something.java:
public class Something extends Application {
// Put application wide (global) variables here
// Constants are final, so they don't have to be private
// But other variables should be declared private;
// use getters/setters to access them
public final boolean FEET = false;
public final boolean METERS = true;
private boolean units = FEET;
#Override
public void onCreate() {
super.onCreate();
// Put any application wide (global) initialization here
}
// Put application wide (global) methods here
public boolean getUnits() {
return units;
}
public void setUnits(boolean whichOne) {
units = whichOne;
}
}
I'm using Eclipse with the ADT plug-in, in Windows XP. Eclipse doesn't always behave properly if you edit XML code directly, so it's best to open AndroidManifest.xml, then select the Application tab and enter your application name in the Name field. You don't need to put a dot or period in front of the name. Just type in the name of your class, like "Globals" or "MyApplication" or whatever. (Note that this is the default application in your Manifest. You don't have to create a separate <application></application> tag.
This step may not be necessary on an actual Android device, but it was necessary for the emulator: you need to use the getApplicationContext() command in every onCreate() and every method that will be accessing the global variables and methods. I tried to put it outside of onCreate() with the rest of my activity wide variables, and it didn't work. Putting it inside every method seems wasteful, but both the emulator and the Android device work fine with it that way. Here's a sample showing how I used it:
public void fooBar() {
// Access to global variables and methods
final Something s = (Something)getApplicationContext();
// ...
// This next line demonstrates both a global method and a global variable
if (s.getUnits() == s.FEET) {
// do something with feet
} else {
// do something with meters instead
}
// ...
}
Those were the only hiccups I encountered. The three references that I have listed, taken together, are otherwise pretty complete.

Most effective way of storing Strings in Android

In my app I have 5 String arrays that represent different fields of objects.
i.e.
String_A[1],
String_B[1],
String_C[1],
String_D[1],
String_E[1],
All are attributes of the same object (which is not really an object).
Now I want to store those in order to be able to use them in a new activity that I am creating. Since you are not able to pass objects around I thought that i should save them in Shared preferences.
My question is: Should I save them as separate strings or create a new class with all those fields and then serialize the objects?
Which is the best way in terms of memory usage? In fact is there any other way that you might achieve similar functionality?
Thanks in advance
Mike
If each of those String Arrays are big "enough" and it appears you do want to store them - have you considered Sqlite? SharedPreferences is most effective to store primitive data in key-value pairs. Check this link - it has neat comparison about the options you have - http://developer.android.com/guide/topics/data/data-storage.html
You can pass around objects via an intent. The extras function of an intent can store a bundle and send it to specified activities, however they cannot be called at any time (like from a later activity without being explicitly sent). If this is a one time pass to a different activity, the you'd probably want to use that.
http://developer.android.com/reference/android/content/Intent.html#putExtras%28android.content.Intent%29
Here is an example from a test app I made a while back:
public void onClick(View v) {
switch(v.getId()) { //this references the unique ID of the view that was clicked
case R.id.Button01: //this is what happens when the Button in the XML with android:id="#+id/Button01" is clicked
Intent nameGreet = new Intent(this, MainMenu.class);//creates Intent which will send the EditText input
String theName = firstName.getText().toString();// creates a new string named "theName" which is the text from an EditText called "firstName"
nameGreet.putExtra("helloName", theName);//puts the input from EditText into the Intent, this is a key/value pair
this.startActivity(nameGreet);//setting off the Intent
break;
Then you catch it like so:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.main_menu);
String personsname = this.getIntent().getStringExtra("helloName");
welcome = (TextView)this.findViewById(R.id.TextView01);
welcome.setText(personsname);
Hope this helps.
You can pass a Serializable using an Intent.
Intent.putExtra(String name, Serializable value).

Categories

Resources