I'm new to android studio and going through intents. I'm creating a registration app which takes user information in first 4 activities and display them altogether in respective views the 5th activity.
My app has personal, professional,address and other detailed activities that are to be retrieved from edit texts and later displayed on the very last screen.
I can only retrieve data only on the next consecutive screen but not save them and add to last activity later on.
Is there any way that i can do the storing and retrieving part using only intents between 2 activities that are not consecutive to each other ? Any help will be appreciated...!!
Yes you can do so by sending the data form one activity to the other activity in chain.
Let say your app starts at ActivityOne then goes to ActivityTwo then to ActivityThree then to ActivityFour then to ActivityFive and submits the data here in ActivityFive. Each activity has a EditText to enter data and a button which on clicking goes to the next activity.
In ActivityOne create and then start an intent on the button click i.e. inside onClick():
Intent i = new Intent(ActivityOne.this,ActivityTwo.class);
i.putExtra("Name",edittext.getText().toString());//get sting from 1st edittext
startActivity(i);
Now your second activity has been started i.e. ActivityTwo.
In that activities onCreate() method create an IntentIntent a = getIntent();
Now in onClick method for the button of this activity do the following:
Intent i = new Intent(ActivityTwo.this,ActivityThree.class);
i.putExtra("Address",edittextTwo.getText().toString());//This line fetches the data from the activities edittext
i.putExtra("Name", a.getStringExtra("Name"));//This line fetches the data from the intent which called this activity.
startActivity(i);
Now in the third activity which has been started i.e. ActivityThree.
Do the same thing in the activities onCreate() method i.e. create an IntentIntent a = getIntent();
Now in onClick method for the button of this activity do the same thing that you did previously but also fetch the data passed from the previous activity:
Intent i = new Intent(ActivityThree.this,ActivityFour.class);
i.putExtra("email",edittextThree.getText().toString());//This line fetches the data from the activity's edittext
i.putExtra("Name", a.getStringExtra("Name"));//This line fetches the data from the intent which called this activity.
i.putExtra("Address", a.getStringExtra("Address"));//This line fetches the data from the intent which called this activity.
startActivity(i);
Continue this in all the activities and in the end you will be able to get all the data in the final activity.
The logic here is to pass the data from one activity to the other and keep on adding data on the go.
There are many ways to pass the data.One easy and efficient way to implement.create a public class in your package.In that class declare your values as static like below.
public class MyDataClass {
public static String name;
public static String userid;
}
you can pass the values like below
MyDataClass myobj=new MyDataClass();
myobj.name="Jhon";
myobj.username="Jhon#gmail.com";
To fetch the value from anywhere Activity or fragment use this
String val=myobj.name;
String val=myobj.username;
You can use singleton class
Create one model class and add the data from that four activites
public class MySingleton {
private UserModel user_details;
private static MySingleton ourInstance = new MySingleton();
public static MySingleton getInstance() {
return ourInstance;
}
private MySingleton() {
}
public void setUserDetails(UserModel news) {
this.user_details= news;
}
public UserModel getUserDetails() {
return user_details;
}
}
//add user details
MySingleton mysingleton= MySingleton .getInstance();
mysingleton.setUserDetails(userdetails); // userdetails - model class object
Use SharedPreference to save your data using key-value pairs. And then you can retrieve the data in any activity using the respective key. Just make sure you use the proper key to save a variable.
public SharedPreferences sharedPref;
public SharedPreferences.Editor editor;
sharedPref = getSharedPreferences("name_of_your_preference", Context.MODE_PRIVATE);
editor = sharedPref.edit();
editor.putString("key" , "value"); //use to save a value
editor.commit();
sharedPref.getString("key", null); // retrieve the data
I'm also new but why not create One Activity which hold the DataModels and collect the UserInformation within Fragments and set them to the Activity on nextBtnClick?
Something like this:
final Button nextFragmentButton = (Button) findViewById(R.id.button_id);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
((MyActivity)getActivity()).setUserDataModel(dataModel)
});
Isnt it a bad design, if you have a lot of activities and put data thru them?
If you would use Fragments, the root activity could hold all the data and would datahandling simplify.
Related
Please give me a hand with an issue I am having with a ListView and its related data in my android development project.
I have an activity called OrderForm that gets started by an Intent from the activity UserProfile as such:
In UserProfile
Intent intent = new Intent(this, OrderForm.class);
startActivity(intent);
Then in OrderForm there is an EditText and an add button to add String items to an ArrayList, and the UI gets populated accordingly.
When I click the back button (back to UserProfile) and go via the Intent to OrderForm again, the UI does not show the list items, why is that?
I realize I can use Room for persistence and even SharedPreferences, but
I wanted to see if there is cleaner, more efficient method, otherwise the less code the better.
Also, maybe I'm not understanding them correctly, but I tried onSaveInstanceState and onRestoreInstanceState and they don't work for me.
Thanks in advance.
Here is part of the code from OrderForm
public class OrderForm extends AppCompatActivity {
ArrayList<String> list;
ListView itemList;
ArrayAdapter<String> arrayAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order_form);
itemList = findViewById(R.id.itemList);
itemText = findViewById(R.id.item);
linearLayout = findViewById(R.id.no_items_container);
orderContainer = findViewById(R.id.orderContainer);
list = new ArrayList<>();
arrayAdapter = new ArrayAdapter<String>(this,
R.layout.list_item,R.id.rowItem, list)
{
#Override
public View getView(int position,
View convertView,
ViewGroup parent) {
// some custom stuff here
}
}
public void addItem(View view)
{
String item = itemText.getText().toString().trim().toLowerCase();
if(!item.isEmpty() && list.indexOf(item) == -1) {
arrayAdapter.add(item);
}
}
You need to understand how Activity lifecycles work.
https://developer.android.com/guide/components/activities/activity-lifecycle.html
Your issue is that when pressing the back button, your OrderForm Activity is destroyed and effectively your arraylist/list view is destroyed. To avoid this problem, you'll have to store the values somewhere for example SharedPreferences, create a text file holding your strings and store it, or return the arraylist back to the UserProfile class where you'll store/handle them (to do that use startActivityForResult() instead of startActivity())
When I click the back button (back to UserProfile) and go via the Intent to OrderForm again, the UI does not show the list items, why is that?
In your onCreate() method, you have this:
list = new ArrayList<>();
arrayAdapter = new ArrayAdapter<String>(..., list)...
Unless you persist your data in some way, list is always going to be empty when your activity starts up.
I realize I can use Room for persistence and even SharedPreferences, but I wanted to see if there is cleaner, more efficient method, otherwise the less code the better.
Exactly what you need to store will help define the best way to store it. For a simple list of strings, probably SharedPreferences is the simplest solution.
Also, maybe I'm not understanding them correctly, but I tried onSaveInstanceState and onRestoreInstanceState and they don't work for me.
These methods are used to store data when an activity is destroyed and then recreated, which commonly happens when the user rotates the device (but can also happen for various other reasons). When you exit your activity (by pressing back to UserProfile), these methods aren't triggered.
I was wondering if anyone could tell me how I could check a checkBox in an activity from another activity.
I'm making a homework app and I want to put a check next to the questions that have been completed.
So the first activity has a list of questions and next to them are unchecked boxes. When you click a question, the app takes you to the second activity. In the second activity, I want to check the box of the question that was completed.
You should use SharedPreferences for that. call this in the first activity:
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.putBoolean("KEY", <your value>).apply();
and something similar in another activity:
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean isTicked = prefs.getBoolean("KEY", <default boolean value>);
where KEY can be anything, for example, your question's number
You should use intent and bundle logic for passing data between activities.(in most cases)
In the first activity, whenever you are creating the second activity, you pass your data.
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
intent.putExtra("checked",checkBox.isChecked());
startActivity(intent);
In the second activity you receive your data by using :
Intent receivedIntent = getIntent();
boolean finalChecked = receivedIntent.getExtras().getBoolean("checked");
//now you can apply your logic with finalChecked variable
You can save checked check question to a bundle and pass it as extra to your second activity through intent and read it from that intent inside your second activity
In your first activity do something like this
public class FirstActivity extends Activity {
public static final String EXTRA_CHECKED_QUESTION = "Checked Question";
// other codes here
private void startSecondActivity() {
String checkedQuestion = getCheckedQuestion(); // a method to get checked question
Intent intent = new Intent(this, SecondActivity.class);
intent.putExtra(FirstActivity.EXTRA_CHECKED_QUESTION, checkedQuestion);
startActivity(intent);
}
}
then in your second activity
public class SecondActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstance) {
// other codes
String checkedQuestion = getIntent().getStringExtra(FirstActivity.EXTRA_CHECKED_QUESTION);
// do whatever you want with checkQuestion
}
}
Please note that the string which you pass as first parameter to putExtra() method in FirstActivity, should be same as the string you are using with getStringExtra() to retrieve your extra in SecondActivity, otherwise you can not retrieve your passed extra in SecondActivity.
Also, I did not write these codes inside idea, so there might be syntax error
Read more about intent here
I'm using Eclipse for windows 7 and I am making an informative application(just text and offline content).
In my app I have about 180 buttons. Each button will lead to another screen. I need to know how to make each button lead to a specific screen?
And also, is there a way to like duplicate the code and not spend hours copying and pasting the code 180 times?
Check my code below for the first two screens:
That's for the MainActivity.java:
public void addListenerOnButton() {
final Context context = this;
button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent = new Intent(context, MainActivity2.class);
startActivity(intent);
}
});
}
I mean that code is only for one single button. Am I supposed to repeat this for every single button?
and also a question, how many classes should I do? 180 main activities, 180 fragment_main.xml and 180 activity_main.xml?
That's my idea, since your application is just a "informative application" you can create two activities:
Main activity with buttons
"Information page"
To do it i need info about how you get this informations:
In a SQLite Database.
In a string-array
Personally, i prefer a SQLite DB it allows you to improve it without problems in the future.
About the Information activity:
Example: in your layout you have a TextView where will be added the text which this activity should be passed.
To make it dynamic in your case we pass the string to show using Intents, in our onCreate we add something like this:
Intent intent = getIntents();
String stringToDisplay = null;
if (intent != null)
{
stringToDisplay = intent.getStringExtra (EXTRA_STRING_CONTENT);
}
getIntents will get the Intent object which is created and passed to it by our main activity. getStringExtra is a simple method which says to Android: i want to get the string which is saved with the key EXTRA_STRING_CONTENT (it's something like a Map)
EXTRA_STRING_CONTENT is a field which we used to make sure we don't make any error in passing data, since we need to use the same name when we pass it (in MainActivity) and when we read it (InformationActivity)
public static final String EXTRA_STRING_CONTENT = "EXTRA_STRING_CONTENT";
Ok, we are done.
We now only need to set the string to our TextView:
TextView infoTextView = (TextView) findViewById(R.id.infotextview);
infoTextView.setText (stringToDisplay);
Stop it.
Now we should go to our MainActivity code and modify our addListenerOnButton
final Context context = this;
button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent = new Intent(context, MainActivity2.class);
startActivity(intent);
}
});
Well, i will focus on this two lines
Intent intent = new Intent(context, MainActivity2.class);
startActivity(intent);
We need to pass the string to display here, how?
Before we used getStringExtra now it's similar (note: it's the same Intent class) but now we need the putExtra method, the compiler will select the correct overload for us so we just need to do
String stringToDisplay = "Hello world";
intent.putExtra(InformativeActivity.EXTRA_STRING_CONTENT, stringToDisplay);
(Note: InformativeActivity.EXTRA_STRING_CONTENT)
With the current code we will always sent Hello world to the second activity but we need something of dynamic based on the button... well now this depends on how you get the data.
If it's a string-array, you can save the string-array in an array and then based on the button (if it's the first sent string index 0, etc.).
An example:
int buttonId = 1; // it will be a general variable, if it's button 1 it will be 0, if 2-1 etc.
String[] informations = getResources().getStringArray(R.array.infos); // in a real code you should move it outside the `onClick` code and put it in a static final field.
intent.putExtra(InformativeActivity.EXTRA_STRING_CONTENT, informations[buttonId]); // it's the same of above
If you understand the concept you will know how to adapt the code based on your needs.
There are some cases where you need more info or what you want to sent is something which is better if managed by the second activity (example: in a sqlite database you could sent only the id of the line and read lines in the second activity based on this id)
Some things which you could change:
Avoid to call it MainActivity2, it's not so helpful as name
You don't need really to save Context, you could just use MainActivity.this
Try to make your addListenerOnButton more general, example take as argument a Button and set the listener to it.. don't read it from XML you will end up with 180 methods for every button.
I am new to android and am working on a fairly basic android application where users are able to create items that are added to a ListView. On creation of each item I create a instance of the 'clicker' class which keeps track of each items name/tick count/other statistics.
when on of the items in the list are clicked it launches a general activity, used by all of the items. I pass the 'clicker' class object to the activity so that it may construct initialize the textviews.
This is what happens when a list item is clicked (the clicker instances are created in a hashmap named clickers, so I first retrieve the key, then call clickers.get(key))
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// pass along some ID so that the new activity can retrieve info
String clickedName = clickerListItems.get(arg2);
Intent intent = new Intent(MainActivity.this, ClickerActivity.class);
intent.putExtra("clickerName", clickers.get(clickedName));
startActivity(intent);
}
This is how the general activity receives the info
public class ClickerActivity extends Activity {
protected Clicker currentClicker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_clicker);
Intent i = getIntent();
currentClicker = (Clicker) i.getSerializableExtra("clickerName");
TextView clickerHeader = (TextView) findViewById(R.id.clickerHeader);
clickerHeader.setText(currentClicker.getName());
final TextView countDisplay = (TextView) findViewById(R.id.countText);
countDisplay.setText(Integer.toString(currentClicker.getCount()));
final Button incrementButton = (Button) findViewById(R.id.incrementButton);
final Button resetButton = (Button) findViewById(R.id.resetButton);
(continues)
here's what the general activity looks like to add some perspective. It's fairly plain right now seeing as I am just starting out.
The issue is that say I click on item A of the ListView and increment it's counter (one of the stats) and then press the back button to return to the List Activity. Now if I click on the same listitem to reload the activity none of the data seems to have been saved. Is the clicker class instance not actually being altered? How do I save the info or restore the info? I would do something onRestoreInstanceState but since this is an activity that may be loaded by any item in the list that wouldn't work, right?
If there any clarification is required please let me know, thank you.
You can use shared preferences, to preserve those values.
http://developer.android.com/reference/android/content/SharedPreferences.html
By using this, none of your data will be lost. Just make sure that when you are starting the app again after killing it, you reset the values stored, so that your values are saved for activity relaunch, but not for app relaunch (unless you want it for that too).
EDIT: You can also put all your main code into an Asynctask(), so that processing would be done in the background and it would be kept alive even when you come out of the app.
A navigation drawer with 3 Fragments, the third Fragment has a TextView with an on Click listener. Once it has been clicked a layout activity will open on the top which includes a ListView to allow the user to select/click on a specific Item, so later on this selected item info should be displayed on that TextView within the third fragment.
is there any method to pass data because I have used a class to pass data but the TextView wouldn't be refreshed with the sent data
This works as a design pattern to share arguments between the Activity and third fragment
--------------------------DataHolder Class---------------------------------
public class DataHolder {
private static DataHolder dataHolder = null;
private DataHolder() {
}
public static DataHolder getInstance() {
if (dataHolder == null)
{dataHolder = new DataHolder(); }
return dataHolder;
}
private String item;
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
}
If you find using startActivityForResult not sufficient in your case or using EventBus, you can overcome this by using SharedPreferences and Fragment/Activity lifecycle.
So once you start new Activity first Activity will go in onPause and with it all its Fragments will be put in onPause. When user clicks on one of the ListView items in your second Activity you can store the value inside SharedPreferences like:
PreferenceManager.getDefaultSharedPreferences(SecondActivity.this)
.edit().putString(key, selectedItemInfoHere).apply();
Then override inside your first Activity and in your third Fragment method onResume() and inside just make checking:
#Override
public void onResume() {
super.onResume();
String value = PreferenceManager.getDefaultSharedPreferences(getContext())
.getString(key, "");
if (value != null && !value.isEmpty()) {
//You have selected item value update TextView
}
}
Note that once you don't need this value you will need to remove it, because it will update your TextView every time when onResume is called. To remove value just call:
PreferenceManager.getDefaultSharedPreferences(getContext()).edit().remove(key);
If I understood you correctly, you have flow 3rd fragment --> activity which should update fragment which launched it. In this case, as for me, the most clean solution is from your opened activity call startActivityForResult method to call activity-host of your fragments and handle all what you need in overridden onActivityResult method. Than just call your fragment's updateTextView() or something like that.
On the other hand you can use this library to send messages between components, but you should be careful with usage and think about corner cases related to components lifecycle.
So, choose solution according your needs:)